From 6aa022f4ebdf84f4aaec9e3d1e3d6afcd92ac48d Mon Sep 17 00:00:00 2001 From: Anurag Chouhan Date: Wed, 19 Sep 2018 12:36:13 +0530 Subject: [PATCH 01/75] icnss: Add check for rejuvenate in fw_down Currently, fw_down is not getting set in case of rejuvenate since the qmi server never exit or arrive in case of rejuvenate. Add ICNSS_REJUVENATE flag to take care of rejuvenate. Change-Id: If85e8048cbad9a15e1c94af1c8d0012e004e6150 Signed-off-by: Anurag Chouhan --- drivers/soc/qcom/icnss.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index d56fb48b0d43..7eb7221835d4 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -1184,7 +1184,8 @@ bool icnss_is_fw_down(void) return false; return test_bit(ICNSS_FW_DOWN, &penv->state) || - test_bit(ICNSS_PD_RESTART, &penv->state); + test_bit(ICNSS_PD_RESTART, &penv->state) || + test_bit(ICNSS_REJUVENATE, &penv->state); } EXPORT_SYMBOL(icnss_is_fw_down); From e6a032c67e2e256c80d22d149d981e915d8951c9 Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Fri, 14 Sep 2018 18:46:06 +0530 Subject: [PATCH 02/75] ASoC: wsa881x: Fix regcache sync issue during playback When temperature on a single wsa881x device is being read, then soundwire master wakes up both wsa881x devices but regcache_sync is happening only for one wsa881x device on which the temperature is being read. This results in audio playback mute after temperature read. Fix the regcache sync during temperature read and playback usecase. CRs-Fixed: 2282230 Change-Id: I054f4432d7ae7bce922341ad62b20544cccd5865 Signed-off-by: Sudheer Papothi Signed-off-by: Laxminath Kasam --- sound/soc/codecs/wsa881x.c | 43 +++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index e4f6df077d98..0c672fd89652 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2018, 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 @@ -76,6 +76,7 @@ struct swr_port { enum { WSA881X_DEV_DOWN, WSA881X_DEV_UP, + WSA881X_DEV_READY, }; /* @@ -99,6 +100,7 @@ struct wsa881x_priv { int version; struct mutex bg_lock; struct mutex res_lock; + struct mutex temp_lock; struct snd_info_entry *entry; struct snd_info_entry *version_entry; int state; @@ -464,6 +466,17 @@ static const struct file_operations codec_debug_ops = { .read = codec_debug_read, }; +static void wsa881x_regcache_sync(struct wsa881x_priv *wsa881x) +{ + mutex_lock(&wsa881x->res_lock); + if (wsa881x->state != WSA881X_DEV_READY) { + regcache_mark_dirty(wsa881x->regmap); + regcache_sync(wsa881x->regmap); + wsa881x->state = WSA881X_DEV_READY; + } + mutex_unlock(&wsa881x->res_lock); +} + static const struct reg_sequence wsa881x_pre_pmu_pa[] = { {WSA881X_SPKR_DRV_GAIN, 0x41, 0}, {WSA881X_SPKR_MISC_CTL1, 0x01, 0}, @@ -790,7 +803,9 @@ static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: + mutex_lock(&wsa881x->temp_lock); wsa881x_resource_acquire(codec, ENABLE); + mutex_unlock(&wsa881x->temp_lock); wsa881x_boost_ctrl(codec, ENABLE); break; case SND_SOC_DAPM_POST_PMD: @@ -798,7 +813,9 @@ static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w, wsa881x->swr_slave->dev_num, false); wsa881x_boost_ctrl(codec, DISABLE); + mutex_lock(&wsa881x->temp_lock); wsa881x_resource_acquire(codec, DISABLE); + mutex_unlock(&wsa881x->temp_lock); break; } return 0; @@ -1042,13 +1059,8 @@ static int32_t wsa881x_temp_reg_read(struct snd_soc_codec *codec, return -EINVAL; } } - mutex_lock(&wsa881x->res_lock); - if (!wsa881x->clk_cnt) { - regcache_mark_dirty(wsa881x->regmap); - regcache_sync(wsa881x->regmap); - } - mutex_unlock(&wsa881x->res_lock); - + wsa881x_regcache_sync(wsa881x); + mutex_lock(&wsa881x->temp_lock); wsa881x_resource_acquire(codec, ENABLE); snd_soc_update_bits(codec, WSA881X_TADC_VALUE_CTL, 0x01, 0x00); @@ -1061,6 +1073,7 @@ static int32_t wsa881x_temp_reg_read(struct snd_soc_codec *codec, wsa_temp_reg->d2_lsb = snd_soc_read(codec, WSA881X_OTP_REG_4); wsa881x_resource_acquire(codec, DISABLE); + mutex_unlock(&wsa881x->temp_lock); return 0; } @@ -1076,7 +1089,6 @@ static int wsa881x_probe(struct snd_soc_codec *codec) dev = wsa881x->swr_slave; wsa881x->codec = codec; mutex_init(&wsa881x->bg_lock); - mutex_init(&wsa881x->res_lock); wsa881x_init(codec); snprintf(wsa881x->tz_pdata.name, sizeof(wsa881x->tz_pdata.name), "%s.%x", "wsatz", (u8)dev->addr); @@ -1098,7 +1110,6 @@ static int wsa881x_remove(struct snd_soc_codec *codec) if (wsa881x->tz_pdata.tz_dev) wsa881x_deinit_thermal(wsa881x->tz_pdata.tz_dev); mutex_destroy(&wsa881x->bg_lock); - mutex_destroy(&wsa881x->res_lock); return 0; } @@ -1224,6 +1235,8 @@ static int wsa881x_swr_probe(struct swr_device *pdev) if (wsa881x->wsa_rst_np) pin_state_current = msm_cdc_pinctrl_get_state( wsa881x->wsa_rst_np); + mutex_init(&wsa881x->res_lock); + mutex_init(&wsa881x->temp_lock); wsa881x_gpio_ctrl(wsa881x, true); wsa881x->state = WSA881X_DEV_UP; @@ -1303,6 +1316,8 @@ static int wsa881x_swr_remove(struct swr_device *pdev) return -EINVAL; } debugfs_remove_recursive(debugfs_wsa881x_dent); + mutex_destroy(&wsa881x->res_lock); + mutex_destroy(&wsa881x->temp_lock); snd_soc_unregister_codec(&pdev->dev); if (wsa881x->pd_gpio) gpio_free(wsa881x->pd_gpio); @@ -1361,6 +1376,11 @@ static int wsa881x_swr_reset(struct swr_device *pdev) dev_err(&pdev->dev, "%s: wsa881x is NULL\n", __func__); return -EINVAL; } + if (wsa881x->state == WSA881X_DEV_READY) { + dev_dbg(&pdev->dev, "%s: device already active\n", __func__); + return 0; + } + wsa881x->bg_cnt = 0; wsa881x->clk_cnt = 0; while (swr_get_logical_dev_num(pdev, pdev->addr, &devnum) && retry--) { @@ -1368,8 +1388,7 @@ static int wsa881x_swr_reset(struct swr_device *pdev) usleep_range(1000, 1100); } pdev->dev_num = devnum; - regcache_mark_dirty(wsa881x->regmap); - regcache_sync(wsa881x->regmap); + wsa881x_regcache_sync(wsa881x); return 0; } From 791c9f35a7b7a3e02ade240a69012c66727ae3d3 Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Fri, 14 Sep 2018 18:50:12 +0530 Subject: [PATCH 03/75] soc: swr-wcd-ctrl: Fix wsa mute issue for stereo playback When temperature on a single wsa881x device is being read, then soundwire master wakes up both wsa881x devices but regcache_sync is happening only for one wsa881x device on which the temperature is being read. This results in audio playback mute after temperature read. Fix the regcache sync during temperature read and playback usecase. CRs-Fixed: 2282230 Change-Id: I856b96517c629ac685bbc25caabee841037106c8 Signed-off-by: Laxminath Kasam --- drivers/soundwire/swr-wcd-ctrl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/soundwire/swr-wcd-ctrl.c b/drivers/soundwire/swr-wcd-ctrl.c index 1dcaba2e79f6..a8458b9b6e3a 100644 --- a/drivers/soundwire/swr-wcd-ctrl.c +++ b/drivers/soundwire/swr-wcd-ctrl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 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 @@ -1727,6 +1727,8 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data) (swrm->state == SWR_MSTR_UP)) { dev_dbg(swrm->dev, "%s: SWR master is already UP: %d\n", __func__, swrm->state); + list_for_each_entry(swr_dev, &mstr->devices, dev_list) + swr_reset_device(swr_dev); } else { pm_runtime_mark_last_busy(&pdev->dev); mutex_unlock(&swrm->reslock); From b010c547d7419a9927dacd4c92db99d77fe2e968 Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Fri, 14 Sep 2018 18:48:04 +0530 Subject: [PATCH 04/75] soc: soundwire: Fix wsa mute issue for stereo playback When stereo playback start and temperature read initiated at same time, one of speaker PA bits are not set in particular race scenario. Handle the broadcast check in soundwire framework to ensure broadcast is disabled only when respective gr_sid slave calls swr_remove_from_group. CRs-Fixed: 2282230 Change-Id: I6f82a8c3c0f39dc20c1def09c1728ce4c26c2f5d Signed-off-by: Laxminath Kasam --- drivers/soundwire/soundwire.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) mode change 100755 => 100644 drivers/soundwire/soundwire.c diff --git a/drivers/soundwire/soundwire.c b/drivers/soundwire/soundwire.c old mode 100755 new mode 100644 index 63545651fe43..0e8cc399204e --- a/drivers/soundwire/soundwire.c +++ b/drivers/soundwire/soundwire.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 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 @@ -241,7 +241,7 @@ int swr_remove_from_group(struct swr_device *dev, u8 dev_num) if (!dev->group_id) return 0; - if (master->gr_sid == dev_num) + if (master->gr_sid != dev_num) return 0; if (master->remove_from_group && master->remove_from_group(master)) From f5220080921498e1726cbc5b977c4687c65b36b2 Mon Sep 17 00:00:00 2001 From: Haibin Liu Date: Mon, 10 Sep 2018 16:02:44 +0800 Subject: [PATCH 05/75] msm: camera: Fix arbitrary kernel write In 64 bit kernel and 32 bit userspace,ioctl_ptr from kernel space, should NOT call the copy_from_user. In 64 bit kernel and 64 bit userspace,ioctl_ptr from user space, use the copy_from_user to copy data. use the is_compat_task to distinguish two condition. CRs-Fixed: 2283160 Change-Id: If9205e4f3176a52e52f694a3183dc9c5b7617a97 Signed-off-by: Haibin Liu --- .../msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c index 58bfdb77a492..bf5296e6d071 100644 --- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c +++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c @@ -570,15 +570,13 @@ static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd, k_ioctl = *ptr; switch (k_ioctl.id) { case MSM_CAMERA_BUF_MNGR_IOCTL_ID_GET_BUF_BY_IDX: { + struct msm_buf_mngr_info buf_info, *tmp = NULL; if (k_ioctl.size != sizeof(struct msm_buf_mngr_info)) return -EINVAL; if (!k_ioctl.ioctl_ptr) return -EINVAL; -#ifndef CONFIG_COMPAT - { - struct msm_buf_mngr_info buf_info, *tmp = NULL; - + if (!is_compat_task()) { MSM_CAM_GET_IOCTL_ARG_PTR(&tmp, &k_ioctl.ioctl_ptr, sizeof(tmp)); if (copy_from_user(&buf_info, tmp, @@ -587,7 +585,7 @@ static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd, } k_ioctl.ioctl_ptr = (uintptr_t)&buf_info; } -#endif + argp = &k_ioctl; rc = msm_cam_buf_mgr_ops(cmd, argp); } From a3c288d3e424c3db224124470aa068fc37525413 Mon Sep 17 00:00:00 2001 From: Anurag Chouhan Date: Wed, 19 Sep 2018 13:15:13 +0530 Subject: [PATCH 06/75] wcnss: Fix buffer overflow in wcnss_prealloc_get There is potential integer truncation in the wcnss_prealloc_get api. size_t is 8 byte on x64 platform and "unsigned int" is 4 byte. To avoid this integer truncation, pass size as size_t instead of unsigned int. CRs-Fixed: 2269610 Change-Id: I14b274dd7cad98b55fdce1aaa27783272231afde Signed-off-by: Anurag Chouhan --- drivers/net/wireless/cnss_prealloc/cnss_prealloc.c | 13 +++++++------ include/linux/wcnss_wlan.h | 2 +- include/net/cnss_prealloc.h | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c b/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c index af64b3dc4da8..9eaa694570ac 100644 --- a/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c +++ b/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef CONFIG_WCNSS_SKB_PRE_ALLOC #include #endif @@ -34,7 +35,7 @@ static struct dentry *debug_base; struct wcnss_prealloc { int occupied; - unsigned int size; + size_t size; void *ptr; #ifdef CONFIG_SLUB_DEBUG unsigned long stack_trace[WCNSS_MAX_STACK_TRACE]; @@ -159,7 +160,7 @@ static inline void wcnss_prealloc_save_stack_trace(struct wcnss_prealloc *entry) } #endif -void *wcnss_prealloc_get(unsigned int size) +void *wcnss_prealloc_get(size_t size) { int i = 0; unsigned long flags; @@ -179,8 +180,8 @@ void *wcnss_prealloc_get(unsigned int size) } spin_unlock_irqrestore(&alloc_lock, flags); - pr_err("wcnss: %s: prealloc not available for size: %d\n", - __func__, size); + pr_err("wcnss: %s: prealloc not available for size: %zu\n", + __func__, size); return NULL; } @@ -219,8 +220,8 @@ void wcnss_prealloc_check_memory_leak(void) j++; } - pr_err("Size: %u, addr: %pK, backtrace:\n", - wcnss_allocs[i].size, wcnss_allocs[i].ptr); + pr_err("Size: %zu, addr: %pK, backtrace:\n", + wcnss_allocs[i].size, wcnss_allocs[i].ptr); print_stack_trace(&wcnss_allocs[i].trace, 1); } diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h index 7389fff7da51..06c652cfb6af 100644 --- a/include/linux/wcnss_wlan.h +++ b/include/linux/wcnss_wlan.h @@ -119,7 +119,7 @@ int wcnss_get_wlan_mac_address(char mac_addr[WLAN_MAC_ADDR_SIZE]); void wcnss_allow_suspend(void); void wcnss_prevent_suspend(void); int wcnss_hardware_type(void); -void *wcnss_prealloc_get(unsigned int size); +void *wcnss_prealloc_get(size_t size); int wcnss_prealloc_put(void *ptr); void wcnss_reset_fiq(bool clk_chk_en); void wcnss_suspend_notify(void); diff --git a/include/net/cnss_prealloc.h b/include/net/cnss_prealloc.h index 734b4b69ecbb..39d080a8b184 100644 --- a/include/net/cnss_prealloc.h +++ b/include/net/cnss_prealloc.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 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,7 @@ #define WCNSS_PRE_ALLOC_GET_THRESHOLD (4*1024) -extern void *wcnss_prealloc_get(unsigned int size); +extern void *wcnss_prealloc_get(size_t size); extern int wcnss_prealloc_put(void *ptr); extern int wcnss_pre_alloc_reset(void); void wcnss_prealloc_check_memory_leak(void); From 4cda48e92cae9352e8208453b282ff273a6c3375 Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Wed, 26 Sep 2018 17:12:10 +0530 Subject: [PATCH 07/75] usb: dwc3-msm: Release PM wakelock in host mode only for auto targets Currently the driver releases PM wakelock in host mode. This causes pm_suspend to get triggered. Although pm_suspend bails out but xhci_bus_suspend transitions the bus to a bad state leading to host mode failure. Fix this by releasing wakelock only for targets on which we allow PM suspend in host mode irrespective of runtimePM. Change-Id: I6648991272c0f22b032b526bce3a76864fec63a5 Signed-off-by: Ajay Agarwal --- drivers/usb/dwc3/dwc3-msm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index dc06f4818e39..920555c64af4 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -3969,7 +3969,10 @@ static void dwc3_otg_sm_work(struct work_struct *w) mdwc->otg_state = OTG_STATE_A_IDLE; goto ret; } - pm_wakeup_event(mdwc->dev, DWC3_WAKEUP_SRC_TIMEOUT); + if (mdwc->no_wakeup_src_in_hostmode) { + pm_wakeup_event(mdwc->dev, + DWC3_WAKEUP_SRC_TIMEOUT); + } } break; @@ -3987,7 +3990,10 @@ static void dwc3_otg_sm_work(struct work_struct *w) dbg_event(0xFF, "XHCIResume", 0); if (dwc) pm_runtime_resume(&dwc->xhci->dev); - pm_wakeup_event(mdwc->dev, DWC3_WAKEUP_SRC_TIMEOUT); + if (mdwc->no_wakeup_src_in_hostmode) { + pm_wakeup_event(mdwc->dev, + DWC3_WAKEUP_SRC_TIMEOUT); + } } break; From 5f7eaf83d807a75e538fbf86dd9fd71c1b814175 Mon Sep 17 00:00:00 2001 From: Liam Mark Date: Thu, 6 Sep 2018 16:15:41 -0700 Subject: [PATCH 08/75] ion: Ensure non-HLOS memory cannot be mapped by CPU Currently it is possible for an ION client to allocate non-HLOS memory (ie memory which isn't assigned to the HLOS vmid), map this memory, and then attempt to access this memory from the CPU. Attempting to access non-HLOS memory from the CPU will cause a stage-2 fault. Fix ION so that non-HLOS memory cannot be mapped by the CPU. Change-Id: Ifb51de2eabc076cddc744c13f01ef97b4a7c6874 Signed-off-by: Liam Mark --- drivers/staging/android/ion/ion_cma_heap.c | 27 +++++++++++++++++-- drivers/staging/android/ion/ion_system_heap.c | 12 +++++++++ .../android/ion/ion_system_secure_heap.c | 10 ++++--- drivers/staging/android/ion/msm/msm_ion.c | 15 +++++++++++ drivers/staging/android/ion/msm/msm_ion.h | 9 ++++++- 5 files changed, 66 insertions(+), 7 deletions(-) diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index 77bc25dfd562..bd481af4035c 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -313,14 +313,37 @@ err: return ret; } +static void *ion_secure_cma_map_kernel(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + if (!is_buffer_hlos_assigned(buffer)) { + pr_info("%s: Mapping non-HLOS accessible buffer disallowed\n", + __func__); + return NULL; + } + return ion_cma_map_kernel(heap, buffer); +} + +static int ion_secure_cma_map_user(struct ion_heap *mapper, + struct ion_buffer *buffer, + struct vm_area_struct *vma) +{ + if (!is_buffer_hlos_assigned(buffer)) { + pr_info("%s: Mapping non-HLOS accessible buffer disallowed\n", + __func__); + return -EINVAL; + } + return ion_cma_mmap(mapper, buffer, vma); +} + static struct ion_heap_ops ion_secure_cma_ops = { .allocate = ion_secure_cma_allocate, .free = ion_secure_cma_free, .map_dma = ion_cma_heap_map_dma, .unmap_dma = ion_cma_heap_unmap_dma, .phys = ion_cma_phys, - .map_user = ion_cma_mmap, - .map_kernel = ion_cma_map_kernel, + .map_user = ion_secure_cma_map_user, + .map_kernel = ion_secure_cma_map_kernel, .unmap_kernel = ion_cma_unmap_kernel, .print_debug = ion_cma_print_debug, }; diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index a2ead280ac4e..403dadea5bb2 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -99,6 +99,11 @@ size_t ion_system_heap_secure_page_pool_total(struct ion_heap *heap, return total << PAGE_SHIFT; } +static int ion_heap_is_system_heap_type(enum ion_heap_type type) +{ + return type == ((enum ion_heap_type)ION_HEAP_TYPE_SYSTEM); +} + static struct page *alloc_buffer_page(struct ion_system_heap *heap, struct ion_buffer *buffer, unsigned long order, @@ -352,6 +357,13 @@ static int ion_system_heap_allocate(struct ion_heap *heap, int vmid = get_secure_vmid(buffer->flags); struct device *dev = heap->priv; + if (ion_heap_is_system_heap_type(buffer->heap->type) && + is_secure_vmid_valid(vmid)) { + pr_info("%s: System heap doesn't support secure allocations\n", + __func__); + return -EINVAL; + } + if (align > PAGE_SIZE) return -EINVAL; diff --git a/drivers/staging/android/ion/ion_system_secure_heap.c b/drivers/staging/android/ion/ion_system_secure_heap.c index 803811597f37..c7585118a41c 100644 --- a/drivers/staging/android/ion/ion_system_secure_heap.c +++ b/drivers/staging/android/ion/ion_system_secure_heap.c @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2018 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 @@ -170,14 +170,15 @@ out: sys_heap->ops->free(&buffer); } -static void process_one_shrink(struct ion_heap *sys_heap, +static void process_one_shrink(struct ion_system_secure_heap *secure_heap, + struct ion_heap *sys_heap, struct prefetch_info *info) { struct ion_buffer buffer; size_t pool_size, size; int ret; - buffer.heap = sys_heap; + buffer.heap = &secure_heap->heap; buffer.flags = info->vmid; pool_size = ion_system_heap_secure_page_pool_total(sys_heap, @@ -192,6 +193,7 @@ static void process_one_shrink(struct ion_heap *sys_heap, } buffer.private_flags = ION_PRIV_FLAG_SHRINKER_FREE; + buffer.heap = sys_heap; sys_heap->ops->free(&buffer); } @@ -211,7 +213,7 @@ static void ion_system_secure_heap_prefetch_work(struct work_struct *work) spin_unlock_irqrestore(&secure_heap->work_lock, flags); if (info->shrink) - process_one_shrink(sys_heap, info); + process_one_shrink(secure_heap, sys_heap, info); else process_one_prefetch(sys_heap, info); diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c index 7326aa46a8f6..116a6fecaac5 100644 --- a/drivers/staging/android/ion/msm/msm_ion.c +++ b/drivers/staging/android/ion/msm/msm_ion.c @@ -678,6 +678,21 @@ int get_secure_vmid(unsigned long flags) return VMID_CP_SPSS_SP_SHARED; return -EINVAL; } + +bool is_buffer_hlos_assigned(struct ion_buffer *buffer) +{ + bool is_hlos = false; + + if (buffer->heap->type == (enum ion_heap_type)ION_HEAP_TYPE_HYP_CMA && + (buffer->flags & ION_FLAG_CP_HLOS)) + is_hlos = true; + + if (get_secure_vmid(buffer->flags) <= 0) + is_hlos = true; + + return is_hlos; +} + /* fix up the cases where the ioctl direction bits are incorrect */ static unsigned int msm_ion_ioctl_dir(unsigned int cmd) { diff --git a/drivers/staging/android/ion/msm/msm_ion.h b/drivers/staging/android/ion/msm/msm_ion.h index 098104d56fdb..f0f01f92c05c 100644 --- a/drivers/staging/android/ion/msm/msm_ion.h +++ b/drivers/staging/android/ion/msm/msm_ion.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016, 2018, 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 @@ -175,6 +175,8 @@ int msm_ion_do_cache_offset_op( void *vaddr, unsigned int offset, unsigned long len, unsigned int cmd); +bool is_buffer_hlos_assigned(struct ion_buffer *buffer); + #else static inline struct ion_client *msm_ion_client_create(const char *name) { @@ -202,6 +204,11 @@ int msm_ion_do_cache_offset_op( return -ENODEV; } +static bool is_buffer_hlos_assigned(struct ion_buffer *buffer) +{ + return true; +} + #endif /* CONFIG_ION */ #endif From dfeb476fb6457986f4e3ea891be4c2e7b0a2f016 Mon Sep 17 00:00:00 2001 From: Fei Mao Date: Fri, 28 Sep 2018 18:44:25 +0800 Subject: [PATCH 09/75] ARM: dts: msm: remove HOME gpio key for qrd devices For qrd devices, remove HOME gpio key to fix driver probe issue. Change-Id: I46ba4ef05c795fced67f2db59a3f5ce183bdeba8 Signed-off-by: Fei Mao --- arch/arm/boot/dts/qcom/sdm630-qrd.dtsi | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi index 384e24d221c4..82e80891e05d 100644 --- a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, 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 @@ -366,16 +366,6 @@ gpio-key,wakeup; debounce-interval = <15>; }; - - home { - label = "home"; - gpios = <&pm660_gpios 11 0x1>; - linux,input-type = <1>; - linux,code = <102>; - gpio-key,wakeup; - debounce-interval = <15>; - }; - }; hbtp { From e950a87576969dca17e5968bb7eaecd7e93aab9c Mon Sep 17 00:00:00 2001 From: Vipin Deep Kaur Date: Mon, 8 Oct 2018 17:08:43 +0530 Subject: [PATCH 10/75] i2c-msm-v2: Handle Null pointer de-reference Zero message may be passed causing null pointer de-reference. Adding check on the number of messages passed to handle the issue. Change-Id: I7cef6dd2070c5eaaa748698c45540f8aa1d96116 Signed-off-by: Vipin Deep Kaur --- drivers/i2c/busses/i2c-msm-v2.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/i2c/busses/i2c-msm-v2.c b/drivers/i2c/busses/i2c-msm-v2.c index d72953f2df23..198e55829226 100644 --- a/drivers/i2c/busses/i2c-msm-v2.c +++ b/drivers/i2c/busses/i2c-msm-v2.c @@ -2330,6 +2330,12 @@ i2c_msm_frmwrk_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) struct i2c_msm_ctrl *ctrl = i2c_get_adapdata(adap); struct i2c_msm_xfer *xfer = &ctrl->xfer; + if (num < 1) { + dev_err(ctrl->dev, + "error on number of msgs(%d) received\n", num); + return -EINVAL; + } + if (IS_ERR_OR_NULL(msgs)) { dev_err(ctrl->dev, " error on msgs Accessing invalid pointer location\n"); return PTR_ERR(msgs); From eea18ae6b7c86fbdfa91897deb8ef7ec12385ea2 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Fri, 21 Sep 2018 11:42:40 +0530 Subject: [PATCH 11/75] msm: ipa: Protect ipa default routing table Protect ipa default routing table from addition, deletion and modification once after default rule added by ipa-driver. Change-Id: I045d9c29fed23edf796d826e440b81124e1f666a Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v3/ipa_rt.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c index a260dbe010f3..8f6024c51e1d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c @@ -1047,13 +1047,12 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, goto error; } /* - * do not allow any rules to be added at end of the "default" routing - * tables + * do not allow any rule to be added at "default" routing + * table */ if (!strcmp(tbl->name, IPA_DFLT_RT_TBL_NAME) && - (tbl->rule_cnt > 0) && (at_rear != 0)) { - IPAERR_RL("cannot add rule at end of tbl rule_cnt=%d at_rear=%d" - , tbl->rule_cnt, at_rear); + (tbl->rule_cnt > 0)) { + IPAERR_RL("cannot add rules to default rt table\n"); goto error; } @@ -1275,13 +1274,12 @@ int ipa3_add_rt_rule_after(struct ipa_ioc_add_rt_rule_after *rules) } /* - * do not allow any rules to be added at end of the "default" routing - * tables + * do not allow any rule to be added at "default" routing + * table */ if (!strcmp(tbl->name, IPA_DFLT_RT_TBL_NAME) && - (&entry->link == tbl->head_rt_rule_list.prev)) { - IPAERR_RL("cannot add rule at end of tbl rule_cnt=%d\n", - tbl->rule_cnt); + (tbl->rule_cnt > 0)) { + IPAERR_RL("cannot add rules to default rt table\n"); ret = -EINVAL; goto bail; } @@ -1740,6 +1738,10 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) goto error; } + if (!strcmp(entry->tbl->name, IPA_DFLT_RT_TBL_NAME)) { + IPAERR_RL("Default tbl rule cannot be modified\n"); + return -EINVAL; + } /* Adding check to confirm still * header entry present in header table or not */ From 28dfcdc51abf85dbc8666f3dca4a6803bff9ebd1 Mon Sep 17 00:00:00 2001 From: Amine Najahi Date: Mon, 17 Sep 2018 16:05:25 -0400 Subject: [PATCH 12/75] fbdev/msm: sanitize debugfs inputs when reading mdp memory Sanitize debugfs inputs to only allow access to mdp memory block specified in dtsi file. This change will allow only one single block to be read at the time and will avoid accessing memory outside of valid decode space which can trigger AHB error bus response. Change-Id: Icede9a8939a66faa59d674c18183fb0ebcf67908 Signed-off-by: Amine Najahi --- drivers/video/fbdev/msm/mdss_debug.c | 41 ++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_debug.c b/drivers/video/fbdev/msm/mdss_debug.c index 230b02061b39..e9989fbdd2ba 100644 --- a/drivers/video/fbdev/msm/mdss_debug.c +++ b/drivers/video/fbdev/msm/mdss_debug.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2009-2018, 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 @@ -433,6 +433,39 @@ static int mdss_debug_base_release(struct inode *inode, struct file *file) return 0; } +/** + * mdss_debug_base_is_valid_range - verify if requested memory range is valid + * @off: address offset in bytes + * @cnt: memory size in bytes + * Return: true if valid; false otherwise + */ +static bool mdss_debug_base_is_valid_range(u32 off, u32 cnt) +{ + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + struct mdss_debug_data *mdd = mdata->debug_inf.debug_data; + struct range_dump_node *node; + struct mdss_debug_base *base; + + pr_debug("check offset=0x%x cnt=0x%x\n", off, cnt); + + list_for_each_entry(base, &mdd->base_list, head) { + list_for_each_entry(node, &base->dump_list, head) { + pr_debug("%s: start=0x%x end=0x%x\n", node->range_name, + node->offset.start, node->offset.end); + + if (node->offset.start <= off + && off <= node->offset.end + && off + cnt <= node->offset.end) { + pr_debug("valid range requested\n"); + return true; + } + } + } + + pr_err("invalid range requested\n"); + return false; +} + static ssize_t mdss_debug_base_offset_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { @@ -452,7 +485,8 @@ static ssize_t mdss_debug_base_offset_write(struct file *file, buf[count] = 0; /* end of string */ - sscanf(buf, "%5x %x", &off, &cnt); + if (sscanf(buf, "%5x %x", &off, &cnt) != 2) + return -EFAULT; if (off % sizeof(u32)) return -EINVAL; @@ -463,6 +497,9 @@ static ssize_t mdss_debug_base_offset_write(struct file *file, if (cnt > (dbg->max_offset - off)) cnt = dbg->max_offset - off; + if (!mdss_debug_base_is_valid_range(off, cnt)) + return -EINVAL; + mutex_lock(&mdss_debug_lock); dbg->off = off; dbg->cnt = cnt; From 509dc323d388807b975e1d29432c1989a578804b Mon Sep 17 00:00:00 2001 From: Padmanabhan Komanduru Date: Tue, 18 Sep 2018 18:26:01 +0530 Subject: [PATCH 13/75] clk: qcom: mdss: add support for dynamic refresh on DSI 14nm PLL Add CLK_SET_RATE_NO_REPARENT flag for the software mux clocks in DSI 14nm PLL driver which is needed for dynamic refresh feature. Update the dynamic fps structure to align the PLL codes with vco frequency instead of fps. Change-Id: I533f615ce51be7229171b6accac3f14ab2dca949 Signed-off-by: Padmanabhan Komanduru --- drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c | 14 ++++++++++---- drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.c | 14 +++++++++----- drivers/clk/qcom/mdss/mdss-pll.h | 14 +++----------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c index d388073f5f42..b885428d3eb7 100644 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c +++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c @@ -41,13 +41,13 @@ static int mdss_pll_read_stored_trim_codes( goto end_read; } - for (i = 0; i < dsi_pll_res->dfps->panel_dfps.frame_rate_cnt; i++) { + for (i = 0; i < dsi_pll_res->dfps->vco_rate_cnt; i++) { struct dfps_codes_info *codes_info = &dsi_pll_res->dfps->codes_dfps[i]; - pr_debug("valid=%d frame_rate=%d, vco_rate=%d, code %d %d\n", - codes_info->is_valid, codes_info->frame_rate, - codes_info->clk_rate, codes_info->pll_codes.pll_codes_1, + pr_debug("valid=%d vco_rate=%d, code %d %d\n", + codes_info->is_valid, codes_info->clk_rate, + codes_info->pll_codes.pll_codes_1, codes_info->pll_codes.pll_codes_2); if (vco_clk_rate != codes_info->clk_rate && @@ -953,7 +953,13 @@ static void shadow_pll_dynamic_refresh_14nm(struct mdss_pll_resources *pll, struct dsi_pll_db *pdb) { struct dsi_pll_output *pout = &pdb->out; + u32 data = 0; + data = (pout->pll_n1div | (pout->pll_n2div << 4)); + MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, + DSI_DYNAMIC_REFRESH_PLL_CTRL19, + DSIPHY_CMN_CLK_CFG0, DSIPHY_CMN_CLK_CFG1, + data, 1); MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL20, DSIPHY_CMN_CTRL_0, DSIPHY_PLL_SYSCLK_EN_RESET, diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.c index 667a1512d54f..bf3532133487 100644 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.c +++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2018 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 @@ -323,7 +323,8 @@ static struct clk_regmap_mux dsi0pll_pixel_clk_mux = { (const char *[]){ "dsi0pll_pixel_clk_src", "dsi0pll_shadow_pixel_clk_src"}, .num_parents = 2, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT), .ops = &clk_regmap_mux_closest_ops, }, }, @@ -341,7 +342,8 @@ static struct clk_regmap_mux dsi1pll_pixel_clk_mux = { (const char *[]){ "dsi1pll_pixel_clk_src", "dsi1pll_shadow_pixel_clk_src"}, .num_parents = 2, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT), .ops = &clk_regmap_mux_closest_ops, }, }, @@ -414,7 +416,8 @@ static struct clk_regmap_mux dsi0pll_byte_clk_mux = { "dsi0pll_shadow_byte_clk_src"}, .num_parents = 2, .ops = &clk_regmap_mux_closest_ops, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT), }, }, }; @@ -432,7 +435,8 @@ static struct clk_regmap_mux dsi1pll_byte_clk_mux = { "dsi1pll_shadow_byte_clk_src"}, .num_parents = 2, .ops = &clk_regmap_mux_closest_ops, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT), }, }, }; diff --git a/drivers/clk/qcom/mdss/mdss-pll.h b/drivers/clk/qcom/mdss/mdss-pll.h index 369c36407ff7..5af107db8b1b 100644 --- a/drivers/clk/qcom/mdss/mdss-pll.h +++ b/drivers/clk/qcom/mdss/mdss-pll.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, 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 @@ -57,13 +57,7 @@ enum { MDSS_PLL_TARGET_SDM630, }; -#define DFPS_MAX_NUM_OF_FRAME_RATES 20 - -struct dfps_panel_info { - uint32_t enabled; - uint32_t frame_rate_cnt; - uint32_t frame_rate[DFPS_MAX_NUM_OF_FRAME_RATES]; /* hz */ -}; +#define DFPS_MAX_NUM_OF_FRAME_RATES 16 struct dfps_pll_codes { uint32_t pll_codes_1; @@ -72,15 +66,13 @@ struct dfps_pll_codes { struct dfps_codes_info { uint32_t is_valid; - uint32_t frame_rate; /* hz */ uint32_t clk_rate; /* hz */ struct dfps_pll_codes pll_codes; }; struct dfps_info { - struct dfps_panel_info panel_dfps; + uint32_t vco_rate_cnt; struct dfps_codes_info codes_dfps[DFPS_MAX_NUM_OF_FRAME_RATES]; - void *dfps_fb_base; }; struct mdss_pll_resources { From 1f9d195b19b8a251ac816ac8ea6842806946a4c2 Mon Sep 17 00:00:00 2001 From: Padmanabhan Komanduru Date: Tue, 18 Sep 2018 18:27:15 +0530 Subject: [PATCH 14/75] ARM: dts: msm: add DT properties for dynamic refresh for SDM660/SDM630 Add the DT properties in DSI controller/PLL nodes/memory nodes which are needed for supporting dynamic refresh feature for SDM660/SDM630. Change-Id: Iccfaf219705de28eb4bd721987075eab09b0120f Signed-off-by: Padmanabhan Komanduru --- arch/arm/boot/dts/qcom/sdm630-mdss-pll.dtsi | 7 +++--- arch/arm/boot/dts/qcom/sdm630-mdss.dtsi | 15 ++++++++--- arch/arm/boot/dts/qcom/sdm630.dtsi | 7 +++++- arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi | 13 ++++++---- arch/arm/boot/dts/qcom/sdm660-mdss.dtsi | 28 +++++++++++++++++---- arch/arm/boot/dts/qcom/sdm660.dtsi | 7 +++++- 6 files changed, 59 insertions(+), 18 deletions(-) diff --git a/arch/arm/boot/dts/qcom/sdm630-mdss-pll.dtsi b/arch/arm/boot/dts/qcom/sdm630-mdss-pll.dtsi index 42eac0ab223a..3adf92a76347 100644 --- a/arch/arm/boot/dts/qcom/sdm630-mdss-pll.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630-mdss-pll.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, 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,8 +19,9 @@ #clock-cells = <1>; reg = <0xc994400 0x588>, - <0xc8c2300 0x8>; - reg-names = "pll_base", "gdsc_base"; + <0xc8c2300 0x8>, + <0xc994200 0x98>; + reg-names = "pll_base", "gdsc_base", "dynamic_pll_base"; gdsc-supply = <&gdsc_mdss>; diff --git a/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi index d7fef426d4b6..de06a67db1b9 100644 --- a/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, 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 @@ -359,10 +359,19 @@ <&clock_mmss MMSS_MDSS_ESC0_CLK>, <&clock_mmss BYTE0_CLK_SRC>, <&clock_mmss PCLK0_CLK_SRC>, - <&clock_mmss MMSS_MDSS_BYTE0_INTF_CLK>; + <&clock_mmss MMSS_MDSS_BYTE0_INTF_CLK>, + <&mdss_dsi0_pll BYTE0_MUX_CLK>, + <&mdss_dsi0_pll PIX0_MUX_CLK>, + <&mdss_dsi0_pll BYTE0_SRC_CLK>, + <&mdss_dsi0_pll PIX0_SRC_CLK>, + <&mdss_dsi0_pll SHADOW_BYTE0_SRC_CLK>, + <&mdss_dsi0_pll SHADOW_PIX0_SRC_CLK>; clock-names = "byte_clk", "pixel_clk", "core_clk", "byte_clk_rcg", "pixel_clk_rcg", - "byte_intf_clk"; + "byte_intf_clk", "pll_byte_clk_mux", + "pll_pixel_clk_mux", "pll_byte_clk_src", + "pll_pixel_clk_src", "pll_shadow_byte_clk_src", + "pll_shadow_pixel_clk_src"; qcom,platform-strength-ctrl = [ff 06 ff 06 diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi index 8873627e64d6..8b637619acbd 100644 --- a/arch/arm/boot/dts/qcom/sdm630.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630.dtsi @@ -406,9 +406,14 @@ }; cont_splash_mem: splash_region@9d400000 { - reg = <0x0 0x9d400000 0x0 0x02400000>; + reg = <0x0 0x9d400000 0x0 0x23ff000>; label = "cont_splash_mem"; }; + + dfps_data_mem: dfps_data_mem@0x9f7ff000 { + reg = <0 0x9f7ff000 0 0x00001000>; + label = "dfps_data_mem"; + }; }; bluetooth: bt_wcn3990 { diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi index 69d3736d4ba8..a3b6aadd893e 100644 --- a/arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, 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,8 +19,9 @@ #clock-cells = <1>; reg = <0xc994400 0x588>, - <0xc8c2300 0x8>; - reg-names = "pll_base", "gdsc_base"; + <0xc8c2300 0x8>, + <0xc994200 0x98>; + reg-names = "pll_base", "gdsc_base", "dynamic_pll_base"; gdsc-supply = <&gdsc_mdss>; @@ -29,6 +30,7 @@ clock-rate = <0>; qcom,dsi-pll-ssc-en; qcom,dsi-pll-ssc-mode = "down-spread"; + memory-region = <&dfps_data_mem>; qcom,platform-supply-entries { #address-cells = <1>; @@ -54,8 +56,9 @@ #clock-cells = <1>; reg = <0xc996400 0x588>, - <0xc8c2300 0x8>; - reg-names = "pll_base", "gdsc_base"; + <0xc8c2300 0x8>, + <0xc996200 0x98>; + reg-names = "pll_base", "gdsc_base", "dynamic_pll_base"; gdsc-supply = <&gdsc_mdss>; diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi index ab4e71e3cd65..b4fbb23c51e4 100644 --- a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, 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 @@ -382,10 +382,19 @@ <&clock_mmss MMSS_MDSS_ESC0_CLK>, <&clock_mmss BYTE0_CLK_SRC>, <&clock_mmss PCLK0_CLK_SRC>, - <&clock_mmss MMSS_MDSS_BYTE0_INTF_CLK>; + <&clock_mmss MMSS_MDSS_BYTE0_INTF_CLK>, + <&mdss_dsi0_pll BYTE0_MUX_CLK>, + <&mdss_dsi0_pll PIX0_MUX_CLK>, + <&mdss_dsi0_pll BYTE0_SRC_CLK>, + <&mdss_dsi0_pll PIX0_SRC_CLK>, + <&mdss_dsi0_pll SHADOW_BYTE0_SRC_CLK>, + <&mdss_dsi0_pll SHADOW_PIX0_SRC_CLK>; clock-names = "byte_clk", "pixel_clk", "core_clk", "byte_clk_rcg", "pixel_clk_rcg", - "byte_intf_clk"; + "byte_intf_clk", "pll_byte_clk_mux", + "pll_pixel_clk_mux", "pll_byte_clk_src", + "pll_pixel_clk_src", "pll_shadow_byte_clk_src", + "pll_shadow_pixel_clk_src"; qcom,null-insertion-enabled; qcom,platform-strength-ctrl = [ff 06 @@ -423,10 +432,19 @@ <&clock_mmss MMSS_MDSS_ESC1_CLK>, <&clock_mmss BYTE1_CLK_SRC>, <&clock_mmss PCLK1_CLK_SRC>, - <&clock_mmss MMSS_MDSS_BYTE1_INTF_CLK>; + <&clock_mmss MMSS_MDSS_BYTE1_INTF_CLK>, + <&mdss_dsi1_pll BYTE1_MUX_CLK>, + <&mdss_dsi1_pll PIX1_MUX_CLK>, + <&mdss_dsi1_pll BYTE1_SRC_CLK>, + <&mdss_dsi1_pll PIX1_SRC_CLK>, + <&mdss_dsi1_pll SHADOW_BYTE1_SRC_CLK>, + <&mdss_dsi1_pll SHADOW_PIX1_SRC_CLK>; clock-names = "byte_clk", "pixel_clk", "core_clk", "byte_clk_rcg", "pixel_clk_rcg", - "byte_intf_clk"; + "byte_intf_clk", "pll_byte_clk_mux", + "pll_pixel_clk_mux", "pll_byte_clk_src", + "pll_pixel_clk_src", "pll_shadow_byte_clk_src", + "pll_shadow_pixel_clk_src"; qcom,null-insertion-enabled; qcom,platform-strength-ctrl = [ff 06 diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi index 5161a9ef6d10..e8f32390704e 100644 --- a/arch/arm/boot/dts/qcom/sdm660.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660.dtsi @@ -404,9 +404,14 @@ }; cont_splash_mem: splash_region@9d400000 { - reg = <0x0 0x9d400000 0x0 0x02400000>; + reg = <0x0 0x9d400000 0x0 0x23ff000>; label = "cont_splash_mem"; }; + + dfps_data_mem: dfps_data_mem@0x9f7ff000 { + reg = <0 0x9f7ff000 0 0x00001000>; + label = "dfps_data_mem"; + }; }; bluetooth: bt_wcn3990 { From 7c085a95a7f63b0ff1f27fef38a00810177dc737 Mon Sep 17 00:00:00 2001 From: Padmanabhan Komanduru Date: Tue, 25 Sep 2018 07:47:48 +0530 Subject: [PATCH 15/75] msm: mdss: add support to switch the DSI clock dynamically Add change to support changing the DSI bit clock dynamically for video mode panels. This helps to avoid interference of DSI clock with other subsystems runtime. Change-Id: I05790a6dd9d8a2fc3cf31727d032e5220d6164e5 Signed-off-by: Padmanabhan Komanduru --- .../devicetree/bindings/fb/mdss-dsi-panel.txt | 6 + drivers/video/fbdev/msm/mdss_dsi.c | 331 ++++++++++++++---- drivers/video/fbdev/msm/mdss_dsi.h | 6 +- drivers/video/fbdev/msm/mdss_dsi_panel.c | 32 +- drivers/video/fbdev/msm/mdss_dsi_phy.c | 31 +- drivers/video/fbdev/msm/mdss_dsi_phy.h | 4 +- drivers/video/fbdev/msm/mdss_fb.c | 6 +- drivers/video/fbdev/msm/mdss_panel.h | 3 + drivers/video/fbdev/msm/msm_mdss_io_8974.c | 103 ++++-- 9 files changed, 388 insertions(+), 134 deletions(-) diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt index cc55f6e2bfa0..4d0e1d5e12a2 100644 --- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt +++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt @@ -165,6 +165,9 @@ Optional properties: - qcom,mdss-dsi-border-color: Defines the border color value if border is present. 0 = default value. - qcom,mdss-dsi-pan-enable-dynamic-fps: Boolean used to enable change in frame rate dynamically. +- qcom,mdss-dsi-pan-enable-dynamic-bitclk: Boolean used to enable change in DSI clock dynamically. +- qcom,mdss-dsi-dynamic-bitclk_freq: An array of integers that specifies the DSI bit clock + frequencies supported as part of dynamic bit clock feature. - qcom,mdss-dsi-pan-fps-update: A string that specifies when to change the frame rate. "dfps_suspend_resume_mode"= FPS change request is implemented during suspend/resume. @@ -696,6 +699,9 @@ Example: qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; qcom,mdss-dsi-pan-enable-dynamic-fps; qcom,mdss-dsi-pan-fps-update = "dfps_suspend_resume_mode"; + qcom,mdss-dsi-pan-enable-dynamic-bitclk; + qcom,mdss-dsi-dynamic-bitclk_freq = <711037824 724453632 737869440 + 751285248 764701056 778116864 791532672 804948480>; qcom,min-refresh-rate = <30>; qcom,max-refresh-rate = <60>; qcom,mdss-dsi-bl-pmic-bank-select = <0>; diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index 0d41f41371dd..69b9149cd750 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -2043,10 +2043,9 @@ static void __mdss_dsi_calc_dfps_delay(struct mdss_panel_data *pdata) } static int __mdss_dsi_dfps_calc_clks(struct mdss_panel_data *pdata, - int new_fps) + u64 new_clk_rate) { int rc = 0; - u64 clk_rate; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_panel_info *pinfo; u32 phy_rev; @@ -2066,14 +2065,9 @@ static int __mdss_dsi_dfps_calc_clks(struct mdss_panel_data *pdata, pinfo = &pdata->panel_info; phy_rev = ctrl_pdata->shared_data->phy_rev; - rc = mdss_dsi_clk_div_config - (&ctrl_pdata->panel_data.panel_info, new_fps); - if (rc) { - pr_err("%s: unable to initialize the clk dividers\n", - __func__); - return rc; - } - + pinfo->clk_rate = new_clk_rate; + pinfo->mipi.dsi_pclk_rate = mdss_dsi_get_pclk_rate(pinfo, + new_clk_rate); __mdss_dsi_dyn_refresh_config(ctrl_pdata); if (phy_rev == DSI_PHY_REV_20) @@ -2086,9 +2080,8 @@ static int __mdss_dsi_dfps_calc_clks(struct mdss_panel_data *pdata, ctrl_pdata->byte_clk_rate_bkp = ctrl_pdata->byte_clk_rate; ctrl_pdata->pclk_rate = pinfo->mipi.dsi_pclk_rate; - clk_rate = pinfo->clk_rate; - do_div(clk_rate, 8U); - ctrl_pdata->byte_clk_rate = (u32) clk_rate; + do_div(new_clk_rate, 8U); + ctrl_pdata->byte_clk_rate = (u32) new_clk_rate; pr_debug("byte_rate=%i\n", ctrl_pdata->byte_clk_rate); pr_debug("pclk_rate=%i\n", ctrl_pdata->pclk_rate); @@ -2096,8 +2089,7 @@ static int __mdss_dsi_dfps_calc_clks(struct mdss_panel_data *pdata, return rc; } -static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata, - int new_fps) +static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata) { struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_dsi_ctrl_pdata *sctrl_pdata = NULL; @@ -2248,12 +2240,6 @@ static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata, clk_disable_unprepare(ctrl_pdata->pll_byte_clk); clk_disable_unprepare(ctrl_pdata->pll_pixel_clk); - /* update new fps that at this point is already updated in hw */ - pinfo->current_fps = new_fps; - if (sctrl_pdata) { - spinfo->current_fps = new_fps; - } - return rc; dfps_timeout: @@ -2330,13 +2316,65 @@ static void mdss_dsi_avr_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata, MDSS_XLOG(ctrl_pdata->ndx, enabled, data); } -static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) +static int __mdss_dsi_dynamic_clock_switch(struct mdss_panel_data *pdata, + u64 new_clk_rate) { int rc = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_panel_info *pinfo; u32 phy_rev; - u32 frame_rate_bkp; + u64 clk_rate_bkp; + + pr_debug("%s+:\n", __func__); + + ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, + panel_data); + + phy_rev = ctrl_pdata->shared_data->phy_rev; + pinfo = &pdata->panel_info; + + /* get the fps configured in HW */ + clk_rate_bkp = pinfo->clk_rate; + + __mdss_dsi_mask_dfps_errors(ctrl_pdata, true); + + if (phy_rev == DSI_PHY_REV_20) { + rc = mdss_dsi_phy_calc_timing_param(pinfo, phy_rev, + new_clk_rate); + if (rc) { + pr_err("PHY calculations failed-%lld\n", new_clk_rate); + goto end_update; + } + } + + rc = __mdss_dsi_dfps_calc_clks(pdata, new_clk_rate); + if (rc) { + pr_err("error calculating clocks for %lld\n", new_clk_rate); + goto error_clks; + } + + rc = __mdss_dsi_dfps_update_clks(pdata); + if (rc) { + pr_err("Dynamic refresh failed-%lld\n", new_clk_rate); + goto error_dfps; + } + return rc; +error_dfps: + if (__mdss_dsi_dfps_calc_clks(pdata, clk_rate_bkp)) + pr_err("error reverting clock calculations for %lld\n", + clk_rate_bkp); +error_clks: + if (mdss_dsi_phy_calc_timing_param(pinfo, phy_rev, clk_rate_bkp)) + pr_err("Unable to revert phy timing-%lld\n", clk_rate_bkp); +end_update: + return rc; +} + +static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) +{ + int rc = 0; + struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; + struct mdss_panel_info *pinfo; pr_debug("%s+:\n", __func__); @@ -2353,12 +2391,8 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) return -EINVAL; } - phy_rev = ctrl_pdata->shared_data->phy_rev; pinfo = &pdata->panel_info; - /* get the fps configured in HW */ - frame_rate_bkp = pinfo->current_fps; - if (new_fps == pinfo->current_fps) { /* * This is unlikely as mdss driver checks for previously @@ -2374,39 +2408,45 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) __mdss_dsi_update_video_mode_total(pdata, new_fps); } else if (pinfo->dfps_update == DFPS_IMMEDIATE_CLK_UPDATE_MODE) { /* Clock update method */ + u64 new_clk_rate = mdss_dsi_calc_bitclk + (&ctrl_pdata->panel_data.panel_info, new_fps); + if (!new_clk_rate) { + pr_err("%s: unable to get the new bit clock rate\n", + __func__); + rc = -EINVAL; + goto end_update; + } - __mdss_dsi_mask_dfps_errors(ctrl_pdata, true); + rc = __mdss_dsi_dynamic_clock_switch(pdata, new_clk_rate); + if (!rc) { + struct mdss_dsi_ctrl_pdata *mctrl_pdata = NULL; + struct mdss_panel_info *mpinfo = NULL; - if (phy_rev == DSI_PHY_REV_20) { - rc = mdss_dsi_phy_calc_timing_param(pinfo, phy_rev, - new_fps); - if (rc) { - pr_err("PHY calculations failed-%d\n", new_fps); + if (mdss_dsi_is_hw_config_split + (ctrl_pdata->shared_data) && + mdss_dsi_is_ctrl_clk_master(ctrl_pdata)) goto end_update; + + if (mdss_dsi_is_hw_config_split + (ctrl_pdata->shared_data) && + mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) { + mctrl_pdata = mdss_dsi_get_ctrl_clk_master(); + if (IS_ERR_OR_NULL(mctrl_pdata)) { + pr_err("Invalid mctrl_pdata\n"); + goto end_update; + } + + mpinfo = &mctrl_pdata->panel_data.panel_info; } - } - - rc = __mdss_dsi_dfps_calc_clks(pdata, new_fps); - if (rc) { - pr_err("error calculating clocks for %d\n", new_fps); - goto error_clks; - } - - rc = __mdss_dsi_dfps_update_clks(pdata, new_fps); - if (rc) { - pr_err("Dynamic refresh failed-%d\n", new_fps); - goto error_dfps; + /* + * update new fps that at this point is already + * updated in hw + */ + pinfo->current_fps = new_fps; + if (mctrl_pdata && mpinfo) + mpinfo->current_fps = new_fps; } } - - return rc; -error_dfps: - if (__mdss_dsi_dfps_calc_clks(pdata, frame_rate_bkp)) - pr_err("error reverting clock calculations for %d\n", - frame_rate_bkp); -error_clks: - if (mdss_dsi_phy_calc_timing_param(pinfo, phy_rev, frame_rate_bkp)) - pr_err("Unable to revert phy timing-%d\n", frame_rate_bkp); end_update: return rc; } @@ -2678,6 +2718,163 @@ static void mdss_dsi_timing_db_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, MDSS_DSI_CORE_CLK, MDSS_DSI_CLK_OFF); } +static struct mdss_dsi_ctrl_pdata *mdss_dsi_get_drvdata(struct device *dev) +{ + struct msm_fb_data_type *mfd; + struct mdss_panel_data *pdata; + struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; + struct fb_info *fbi = dev_get_drvdata(dev); + + if (fbi) { + mfd = (struct msm_fb_data_type *)fbi->par; + pdata = dev_get_platdata(&mfd->pdev->dev); + + ctrl_pdata = container_of(pdata, + struct mdss_dsi_ctrl_pdata, panel_data); + } + + return ctrl_pdata; +} + +static ssize_t supp_bitclk_list_sysfs_rda(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + int i = 0; + struct mdss_dsi_ctrl_pdata *ctrl_pdata = mdss_dsi_get_drvdata(dev); + struct mdss_panel_info *pinfo = NULL; + + if (!ctrl_pdata) { + pr_err("%s: invalid input\n", __func__); + return -EINVAL; + } + + pinfo = &ctrl_pdata->panel_data.panel_info; + if (!pinfo) { + pr_err("no panel connected\n"); + return -ENODEV; + } + + if (!pinfo->dynamic_bitclk) { + pr_err_once("%s: Dynamic bitclk not enabled for this panel\n", + __func__); + return -EINVAL; + } + + buf[0] = 0; + for (i = 0; i < pinfo->supp_bitclk_len; i++) { + if (ret > 0) + ret += scnprintf(buf + ret, PAGE_SIZE - ret, + ",%d", pinfo->supp_bitclks[i]); + else + ret += scnprintf(buf + ret, PAGE_SIZE - ret, + "%d", pinfo->supp_bitclks[i]); + } + + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); + + return ret; +} + +static ssize_t dynamic_bitclk_sysfs_wta(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int rc = 0, i = 0; + struct mdss_dsi_ctrl_pdata *ctrl_pdata = mdss_dsi_get_drvdata(dev); + struct mdss_panel_info *pinfo = NULL; + int clk_rate = 0; + + if (!ctrl_pdata) { + pr_err("%s: invalid input\n", __func__); + return -EINVAL; + } + + pinfo = &ctrl_pdata->panel_data.panel_info; + if (!pinfo) { + pr_err("no panel connected\n"); + return -ENODEV; + } + + if (!pinfo->dynamic_bitclk) { + pr_err_once("%s: Dynamic bitclk not enabled for this panel\n", + __func__); + return -EINVAL; + } + + if (mdss_panel_is_power_off(pinfo->panel_power_state)) { + pr_err_once("%s: Panel powered off!\n", __func__); + return -EINVAL; + } + + rc = kstrtoint(buf, 10, &clk_rate); + if (rc) { + pr_err("%s: kstrtoint failed. rc=%d\n", __func__, rc); + return rc; + } + + for (i = 0; i < pinfo->supp_bitclk_len; i++) { + if (pinfo->supp_bitclks[i] == clk_rate) + break; + } + if (i == pinfo->supp_bitclk_len) { + pr_err("Requested bitclk: %d not supported\n", clk_rate); + return -EINVAL; + } + + rc = __mdss_dsi_dynamic_clock_switch(&ctrl_pdata->panel_data, + clk_rate); + if (!rc && mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)) { + struct mdss_dsi_ctrl_pdata *octrl = + mdss_dsi_get_other_ctrl(ctrl_pdata); + rc = __mdss_dsi_dynamic_clock_switch(&octrl->panel_data, + clk_rate); + if (rc) + pr_err("failed to switch DSI bitclk for sctrl\n"); + } else if (rc) { + pr_err("failed to switch DSI bitclk\n"); + } + + return count; +} /* dynamic_bitclk_sysfs_wta */ + +static ssize_t dynamic_bitclk_sysfs_rda(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t ret; + struct mdss_dsi_ctrl_pdata *ctrl_pdata = mdss_dsi_get_drvdata(dev); + struct mdss_panel_info *pinfo = NULL; + + if (!ctrl_pdata) { + pr_err("%s: invalid input\n", __func__); + return -EINVAL; + } + + pinfo = &ctrl_pdata->panel_data.panel_info; + if (!pinfo) { + pr_err("no panel connected\n"); + return -ENODEV; + } + + ret = snprintf(buf, PAGE_SIZE, "%llu\n", pinfo->clk_rate); + pr_debug("%s: '%llu'\n", __func__, pinfo->clk_rate); + + return ret; +} /* dynamic_bitclk_sysfs_rda */ + +static DEVICE_ATTR(dynamic_bitclk, S_IRUGO | S_IWUSR | S_IWGRP, + dynamic_bitclk_sysfs_rda, dynamic_bitclk_sysfs_wta); +static DEVICE_ATTR(supported_bitclk, S_IRUGO, supp_bitclk_list_sysfs_rda, NULL); + +static struct attribute *dynamic_bitclk_fs_attrs[] = { + &dev_attr_dynamic_bitclk.attr, + &dev_attr_supported_bitclk.attr, + NULL, +}; + +static struct attribute_group mdss_dsi_fs_attrs_group = { + .attrs = dynamic_bitclk_fs_attrs, +}; + static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, int event, void *arg) { @@ -2844,6 +3041,14 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, ctrl_pdata->kobj = &fbi->dev->kobj; ctrl_pdata->fb_node = fbi->node; + if (!mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) || + (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) && + mdss_dsi_is_ctrl_clk_master(ctrl_pdata))) { + if (sysfs_create_group(&fbi->dev->kobj, + &mdss_dsi_fs_attrs_group)) + pr_err("failed to create DSI sysfs group\n"); + } + if (IS_ENABLED(CONFIG_MSM_DBA) && pdata->panel_info.is_dba_panel) { queue_delayed_work(ctrl_pdata->workq, @@ -3392,7 +3597,7 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev) pinfo = &(ctrl_pdata->panel_data.panel_info); if (!(mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) && mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) && - pinfo->dynamic_fps) { + (pinfo->dynamic_fps || pinfo->dynamic_bitclk)) { rc = mdss_dsi_shadow_clk_init(pdev, ctrl_pdata); if (rc) { @@ -4359,11 +4564,19 @@ int dsi_panel_device_register(struct platform_device *ctrl_pdev, ((mipi->mode == DSI_VIDEO_MODE) ? MIPI_VIDEO_PANEL : MIPI_CMD_PANEL); - rc = mdss_dsi_clk_div_config(pinfo, mipi->frame_rate); - if (rc) { - pr_err("%s: unable to initialize the clk dividers\n", __func__); - return rc; + pinfo->clk_rate = mdss_dsi_calc_bitclk(pinfo, mipi->frame_rate); + if (!pinfo->clk_rate) { + pr_err("%s: unable to calculate the DSI bit clock\n", __func__); + return -EINVAL; } + + pinfo->mipi.dsi_pclk_rate = mdss_dsi_get_pclk_rate(pinfo, + pinfo->clk_rate); + if (!pinfo->mipi.dsi_pclk_rate) { + pr_err("%s: unable to calculate the DSI pclk\n", __func__); + return -EINVAL; + } + ctrl_pdata->pclk_rate = mipi->dsi_pclk_rate; clk_rate = pinfo->clk_rate; do_div(clk_rate, 8U); diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h index 9847016fed29..900513931547 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.h +++ b/drivers/video/fbdev/msm/mdss_dsi.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, 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 @@ -633,8 +633,8 @@ void disable_esd_thread(void); void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata); void mdss_dsi_set_tx_power_mode(int mode, struct mdss_panel_data *pdata); -int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info, - int frame_rate); +u64 mdss_dsi_calc_bitclk(struct mdss_panel_info *panel_info, int frame_rate); +u32 mdss_dsi_get_pclk_rate(struct mdss_panel_info *panel_info, u64 clk_rate); int mdss_dsi_clk_refresh(struct mdss_panel_data *pdata, bool update_phy); int mdss_dsi_link_clk_init(struct platform_device *pdev, struct mdss_dsi_ctrl_pdata *ctrl_pdata); diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index dbd58f93e907..5ba0480436a2 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, 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 @@ -2324,14 +2324,15 @@ static void mdss_dsi_parse_dfps_config(struct device_node *pan_node, struct mdss_dsi_ctrl_pdata *ctrl_pdata) { const char *data; - bool dynamic_fps; + bool dynamic_fps, dynamic_bitclk; struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info); + int rc = 0; dynamic_fps = of_property_read_bool(pan_node, "qcom,mdss-dsi-pan-enable-dynamic-fps"); if (!dynamic_fps) - return; + goto dynamic_bitclk; pinfo->dynamic_fps = true; data = of_get_property(pan_node, "qcom,mdss-dsi-pan-fps-update", NULL); @@ -2361,6 +2362,31 @@ static void mdss_dsi_parse_dfps_config(struct device_node *pan_node, pinfo->new_fps = pinfo->mipi.frame_rate; pinfo->current_fps = pinfo->mipi.frame_rate; +dynamic_bitclk: + dynamic_bitclk = of_property_read_bool(pan_node, + "qcom,mdss-dsi-pan-enable-dynamic-bitclk"); + if (!dynamic_bitclk) + return; + + of_find_property(pan_node, "qcom,mdss-dsi-dynamic-bitclk_freq", + &pinfo->supp_bitclk_len); + pinfo->supp_bitclk_len = pinfo->supp_bitclk_len/sizeof(u32); + if (pinfo->supp_bitclk_len < 1) + return; + + pinfo->supp_bitclks = kzalloc((sizeof(u32) * pinfo->supp_bitclk_len), + GFP_KERNEL); + if (!pinfo->supp_bitclks) + return; + + rc = of_property_read_u32_array(pan_node, + "qcom,mdss-dsi-dynamic-bitclk_freq", pinfo->supp_bitclks, + pinfo->supp_bitclk_len); + if (rc) { + pr_err("Error from dynamic bitclk freq u64 array read\n"); + return; + } + pinfo->dynamic_bitclk = true; return; } diff --git a/drivers/video/fbdev/msm/mdss_dsi_phy.c b/drivers/video/fbdev/msm/mdss_dsi_phy.c index 2d2498643c3f..e8e903e6ce88 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_phy.c +++ b/drivers/video/fbdev/msm/mdss_dsi_phy.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2018 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 @@ -1034,15 +1034,10 @@ static void mdss_dsi_phy_update_timing_param_v3(struct mdss_panel_info *pinfo, } int mdss_dsi_phy_calc_timing_param(struct mdss_panel_info *pinfo, u32 phy_rev, - u32 frate_hz) + u64 clk_rate) { struct dsi_phy_t_clk_param t_clk; struct dsi_phy_timing t_param; - int hsync_period; - int vsync_period; - unsigned long inter_num; - uint32_t lane_config = 0; - unsigned long x, y; int rc = 0; if (!pinfo) { @@ -1050,30 +1045,12 @@ int mdss_dsi_phy_calc_timing_param(struct mdss_panel_info *pinfo, u32 phy_rev, return -EINVAL; } - hsync_period = mdss_panel_get_htotal(pinfo, true); - vsync_period = mdss_panel_get_vtotal(pinfo); - - inter_num = pinfo->bpp * frate_hz; - - if (pinfo->mipi.data_lane0) - lane_config++; - if (pinfo->mipi.data_lane1) - lane_config++; - if (pinfo->mipi.data_lane2) - lane_config++; - if (pinfo->mipi.data_lane3) - lane_config++; - - x = mult_frac(vsync_period * hsync_period, inter_num, lane_config); - y = rounddown(x, 1); - t_clk.bitclk_mbps = rounddown(mult_frac(y, 1, 1000000), 1); + t_clk.bitclk_mbps = rounddown((uint32_t) div_u64(clk_rate, 1000000), 1); t_clk.escclk_numer = ESC_CLK_MHZ; t_clk.escclk_denom = ESCCLK_MMSS_CC_PREDIV; t_clk.tlpx_numer_ns = TLPX_NUMER; t_clk.treot_ns = TR_EOT; - pr_debug("hperiod=%d, vperiod=%d, inter_num=%lu, lane_cfg=%d\n", - hsync_period, vsync_period, inter_num, lane_config); - pr_debug("x=%lu, y=%lu, bitrate=%d\n", x, y, t_clk.bitclk_mbps); + pr_debug("bitrate=%d\n", t_clk.bitclk_mbps); rc = mdss_dsi_phy_initialize_defaults(&t_clk, &t_param, phy_rev); if (rc) { diff --git a/drivers/video/fbdev/msm/mdss_dsi_phy.h b/drivers/video/fbdev/msm/mdss_dsi_phy.h index 03df17d81f69..b0f7d68556d5 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_phy.h +++ b/drivers/video/fbdev/msm/mdss_dsi_phy.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 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,7 +42,7 @@ enum phy_mode { * @frate_hz - Frame rate for which phy timing parameters are to be calculated. */ int mdss_dsi_phy_calc_timing_param(struct mdss_panel_info *pinfo, u32 phy_rev, - u32 frate_hz); + u64 clk_rate); /* * mdss_dsi_phy_v3_init() - initialization sequence for DSI PHY rev v3 diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index 6c4db0f1f5bd..1b408e2838d6 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -1,7 +1,7 @@ /* * Core MDSS framebuffer driver. * - * Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2008-2018, The Linux Foundation. All rights reserved. * Copyright (C) 2007 Google Incorporated * * This software is licensed under the terms of the GNU General Public @@ -610,7 +610,7 @@ static ssize_t mdss_fb_get_panel_info(struct device *dev, "red_chromaticity_x=%d\nred_chromaticity_y=%d\n" "green_chromaticity_x=%d\ngreen_chromaticity_y=%d\n" "blue_chromaticity_x=%d\nblue_chromaticity_y=%d\n" - "panel_orientation=%d\n", + "panel_orientation=%d\ndyn_bitclk_en=%d\n", pinfo->partial_update_enabled, pinfo->roi_alignment.xstart_pix_align, pinfo->roi_alignment.width_pix_align, @@ -636,7 +636,7 @@ static ssize_t mdss_fb_get_panel_info(struct device *dev, pinfo->hdr_properties.display_primaries[5], pinfo->hdr_properties.display_primaries[6], pinfo->hdr_properties.display_primaries[7], - pinfo->panel_orientation); + pinfo->panel_orientation, pinfo->dynamic_bitclk); return ret; } diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index acac672662c1..de3ff0c77625 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -805,6 +805,9 @@ struct mdss_panel_info { int pwm_lpg_chan; int pwm_period; bool dynamic_fps; + bool dynamic_bitclk; + u32 *supp_bitclks; + u32 supp_bitclk_len; bool ulps_feature_enabled; bool ulps_suspend_enabled; bool panel_ack_disabled; diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c index bb3b4b3fa929..922c4440ba82 100644 --- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c +++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, 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 @@ -1489,13 +1489,19 @@ int mdss_dsi_clk_refresh(struct mdss_panel_data *pdata, bool update_phy) __func__, pinfo->mipi.frame_rate); } - rc = mdss_dsi_clk_div_config(&pdata->panel_info, - pdata->panel_info.mipi.frame_rate); - if (rc) { - pr_err("%s: unable to initialize the clk dividers\n", - __func__); - return rc; + pinfo->clk_rate = mdss_dsi_calc_bitclk(pinfo, pinfo->mipi.frame_rate); + if (!pinfo->clk_rate) { + pr_err("%s: unable to calculate the DSI bit clock\n", __func__); + return -EINVAL; } + + pinfo->mipi.dsi_pclk_rate = mdss_dsi_get_pclk_rate(pinfo, + pinfo->clk_rate); + if (!pinfo->mipi.dsi_pclk_rate) { + pr_err("%s: unable to calculate the DSI pclk\n", __func__); + return -EINVAL; + } + ctrl_pdata->refresh_clk_rate = false; ctrl_pdata->pclk_rate = pdata->panel_info.mipi.dsi_pclk_rate; ctrl_pdata->byte_clk_rate = pdata->panel_info.clk_rate / 8; @@ -1524,7 +1530,7 @@ int mdss_dsi_clk_refresh(struct mdss_panel_data *pdata, bool update_phy) /* phy panel timing calaculation */ rc = mdss_dsi_phy_calc_timing_param(pinfo, ctrl_pdata->shared_data->phy_rev, - pinfo->mipi.frame_rate); + pdata->panel_info.clk_rate); if (rc) { pr_err("Error in calculating phy timings\n"); return rc; @@ -1811,16 +1817,9 @@ bool is_diff_frame_rate(struct mdss_panel_info *panel_info, return (frame_rate != panel_info->mipi.frame_rate); } -int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info, - int frame_rate) +static u8 mdss_dsi_get_lane_cnt(struct mdss_panel_info *panel_info) { - struct mdss_panel_data *pdata = container_of(panel_info, - struct mdss_panel_data, panel_info); - struct mdss_dsi_ctrl_pdata *ctrl_pdata = container_of(pdata, - struct mdss_dsi_ctrl_pdata, panel_data); - u64 h_period, v_period, clk_rate; - u32 dsi_pclk_rate; - u8 lanes = 0, bpp; + u8 lanes = 0; if (!panel_info) return -EINVAL; @@ -1834,7 +1833,17 @@ int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info, if (panel_info->mipi.data_lane0) lanes += 1; - switch (panel_info->mipi.dst_format) { + if (!lanes) + lanes = 1; + + return lanes; +} + +static u8 mdss_dsi_get_bpp(char dst_format) +{ + u8 bpp = 0; + + switch (dst_format) { case DSI_CMD_DST_FORMAT_RGB888: case DSI_VIDEO_DST_FORMAT_RGB888: case DSI_VIDEO_DST_FORMAT_RGB666_LOOSE: @@ -1848,6 +1857,21 @@ int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info, bpp = 3; /* Default format set to RGB888 */ break; } + return bpp; +} + +u64 mdss_dsi_calc_bitclk(struct mdss_panel_info *panel_info, int frame_rate) +{ + struct mdss_panel_data *pdata = container_of(panel_info, + struct mdss_panel_data, panel_info); + struct mdss_dsi_ctrl_pdata *ctrl_pdata = container_of(pdata, + struct mdss_dsi_ctrl_pdata, panel_data); + u64 h_period, v_period, clk_rate = 0; + u8 lanes = 0, bpp; + + lanes = mdss_dsi_get_lane_cnt(panel_info); + + bpp = mdss_dsi_get_bpp(panel_info->mipi.dst_format); h_period = mdss_panel_get_htotal(panel_info, true); if (panel_info->split_link_enabled) @@ -1855,35 +1879,40 @@ int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info, v_period = mdss_panel_get_vtotal(panel_info); if (ctrl_pdata->refresh_clk_rate || is_diff_frame_rate(panel_info, - frame_rate) || (!panel_info->clk_rate)) { - if (lanes > 0) { - panel_info->clk_rate = h_period * v_period * frame_rate - * bpp * 8; - do_div(panel_info->clk_rate, lanes); - } else { - pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__); - panel_info->clk_rate = - h_period * v_period * frame_rate * bpp * 8; - } + frame_rate) || (!panel_info->clk_rate)) { + clk_rate = h_period * v_period * frame_rate * bpp * 8; + do_div(clk_rate, lanes); + } else if (panel_info->clk_rate) { + clk_rate = panel_info->clk_rate; } - if (panel_info->clk_rate == 0) - panel_info->clk_rate = 454000000; + if (clk_rate == 0) + clk_rate = 454000000; + + return clk_rate; +} + +u32 mdss_dsi_get_pclk_rate(struct mdss_panel_info *panel_info, u64 clk_rate) +{ + u8 lanes = 0, bpp; + u32 pclk_rate = 0; + + lanes = mdss_dsi_get_lane_cnt(panel_info); + + bpp = mdss_dsi_get_bpp(panel_info->mipi.dst_format); - clk_rate = panel_info->clk_rate; do_div(clk_rate, 8 * bpp); if (panel_info->split_link_enabled) - dsi_pclk_rate = (u32) clk_rate * + pclk_rate = (u32) clk_rate * panel_info->mipi.lanes_per_sublink; else - dsi_pclk_rate = (u32) clk_rate * lanes; + pclk_rate = (u32) clk_rate * lanes; - if ((dsi_pclk_rate < 3300000) || (dsi_pclk_rate > 250000000)) - dsi_pclk_rate = 35000000; - panel_info->mipi.dsi_pclk_rate = dsi_pclk_rate; + if ((pclk_rate < 3300000) || (pclk_rate > 250000000)) + pclk_rate = 35000000; - return 0; + return pclk_rate; } static bool mdss_dsi_is_ulps_req_valid(struct mdss_dsi_ctrl_pdata *ctrl, From fe63bacdfb04eafb9dde566161b1dc1012d0ab28 Mon Sep 17 00:00:00 2001 From: Padmanabhan Komanduru Date: Tue, 25 Sep 2018 08:13:20 +0530 Subject: [PATCH 16/75] ARM: dts: msm: enable dynamic bit clock for SDM660 MTP panel Add DT properties to enable support for dynamic DSI bit clock feature on NT35597 dual DSI video mode panel on SDM660. Change-Id: I9b382a7a79ba546c8f99889a5a14d2733ea8771f Signed-off-by: Padmanabhan Komanduru --- arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi index b2f4a8ce47d3..4232c8c5d41b 100644 --- a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi @@ -144,6 +144,9 @@ qcom,mdss-dsi-panel-max-error-count = <3>; qcom,mdss-dsi-min-refresh-rate = <53>; qcom,mdss-dsi-max-refresh-rate = <60>; + qcom,mdss-dsi-pan-enable-dynamic-bitclk; + qcom,mdss-dsi-dynamic-bitclk_freq = <711037824 724453632 737869440 + 751285248 764701056 778116864 791532672 804948480>; qcom,mdss-dsi-pan-enable-dynamic-fps; qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp"; }; From 75314b9c3cb144377c43cb6a3c15fc6a046257fe Mon Sep 17 00:00:00 2001 From: Padmanabhan Komanduru Date: Mon, 8 Oct 2018 18:04:18 +0530 Subject: [PATCH 17/75] ARM: dts: msm: update the DSI bit clock for DSI panel on SDM660 Update the DSI bit clock frequencies supported for the NT35597 video mode panel on SDM660 for dynamic bit clock feature. Change-Id: I597bb43bf8f93aa6d98afff5d5b8973689460b41 Signed-off-by: Padmanabhan Komanduru --- arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi index 4232c8c5d41b..6abd62c01fb5 100644 --- a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi @@ -145,8 +145,8 @@ qcom,mdss-dsi-min-refresh-rate = <53>; qcom,mdss-dsi-max-refresh-rate = <60>; qcom,mdss-dsi-pan-enable-dynamic-bitclk; - qcom,mdss-dsi-dynamic-bitclk_freq = <711037824 724453632 737869440 - 751285248 764701056 778116864 791532672 804948480>; + qcom,mdss-dsi-dynamic-bitclk_freq = <798240576 801594528 804948480 + 808302432 811656384>; qcom,mdss-dsi-pan-enable-dynamic-fps; qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp"; }; From dad201d631825bfb8b8831a2775d83cb8ce7cc2d Mon Sep 17 00:00:00 2001 From: Padmanabhan Komanduru Date: Fri, 5 Oct 2018 16:10:04 +0530 Subject: [PATCH 18/75] clk: qcom: mdss: avoid release of the dynamic fps PLL code memory Avoid the release of memory for dynamic fps PLL codes. The memory is part of the continuous splash memory region and will be freed eventually as part of the splash screen memory cleanup routine. Change-Id: I67afb46057770298668ae5790637e8b4b08fd030 Signed-off-by: Padmanabhan Komanduru --- drivers/clk/qcom/mdss/mdss-pll-util.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/drivers/clk/qcom/mdss/mdss-pll-util.c b/drivers/clk/qcom/mdss/mdss-pll-util.c index 881c973ec1b6..d6a148eee68c 100644 --- a/drivers/clk/qcom/mdss/mdss-pll-util.c +++ b/drivers/clk/qcom/mdss/mdss-pll-util.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2016, 2018, 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 @@ -327,16 +327,6 @@ clk_err: return rc; } -static void mdss_pll_free_bootmem(u32 mem_addr, u32 size) -{ - unsigned long pfn_start, pfn_end, pfn_idx; - - pfn_start = mem_addr >> PAGE_SHIFT; - pfn_end = (mem_addr + size) >> PAGE_SHIFT; - for (pfn_idx = pfn_start; pfn_idx < pfn_end; pfn_idx++) - free_reserved_page(pfn_to_page(pfn_idx)); -} - static int mdss_pll_util_parse_dt_dfps(struct platform_device *pdev, struct mdss_pll_resources *pll_res) { @@ -367,7 +357,7 @@ static int mdss_pll_util_parse_dt_dfps(struct platform_device *pdev, area = get_vm_area(offsets[1], VM_IOREMAP); if (!area) { rc = -ENOMEM; - goto dfps_mem_err; + goto pnode_err; } virt_add = (unsigned long)area->addr; @@ -394,10 +384,6 @@ addr_err: ioremap_err: if (area) vfree(area->addr); -dfps_mem_err: - /* free the dfps memory here */ - memblock_free(offsets[0], offsets[1]); - mdss_pll_free_bootmem(offsets[0], offsets[1]); pnode_err: if (pnode) of_node_put(pnode); From 8b68c64261fdc4a64c177022e7017cc82b7b4358 Mon Sep 17 00:00:00 2001 From: Amit Kushwaha Date: Mon, 9 Apr 2018 20:41:14 +0530 Subject: [PATCH 19/75] msm: kgsl: create sysfs entries to expose memory usage Added sysfs entries to show kgsl memory usage statistics. gpumem_mapped: kgsl memory mapped in the process address space. gpumem_unmapped: kgsl allocated memory but not mapped in process. imported_mem: graphics memory not allocated by the kgsl. Below is the sysfs path for new entries: /sys/class/kgsl/kgsl/proc// Change-Id: I08c2014d28dc0ca1e2b54ebf966d00143b303b54 Signed-off-by: Amit Kushwaha --- drivers/gpu/msm/kgsl.c | 11 ++++- drivers/gpu/msm/kgsl_device.h | 2 + drivers/gpu/msm/kgsl_sharedmem.c | 75 ++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 02f0cb7eb16c..0c8c3b90deab 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -459,6 +459,10 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) type = kgsl_memdesc_usermem_type(&entry->memdesc); entry->priv->stats[type].cur -= entry->memdesc.size; + + if (type != KGSL_MEM_ENTRY_ION) + entry->priv->gpumem_mapped -= entry->memdesc.mapsize; + spin_unlock(&entry->priv->mem_lock); kgsl_mmu_put_gpuaddr(&entry->memdesc); @@ -4166,13 +4170,18 @@ static int kgsl_gpumem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct kgsl_mem_entry *entry = vma->vm_private_data; + int ret; if (!entry) return VM_FAULT_SIGBUS; if (!entry->memdesc.ops || !entry->memdesc.ops->vmfault) return VM_FAULT_SIGBUS; - return entry->memdesc.ops->vmfault(&entry->memdesc, vma, vmf); + ret = entry->memdesc.ops->vmfault(&entry->memdesc, vma, vmf); + if ((ret == 0) || (ret == VM_FAULT_NOPAGE)) + entry->priv->gpumem_mapped += PAGE_SIZE; + + return ret; } static void diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index 078109af99fe..6622e89181a9 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -418,6 +418,7 @@ struct kgsl_context { * @kobj: Pointer to a kobj for the sysfs directory for this process * @debug_root: Pointer to the debugfs root for this process * @stats: Memory allocation statistics for this process + * @gpumem_mapped: KGSL memory mapped in the process address space * @syncsource_idr: sync sources created by this process * @syncsource_lock: Spinlock to protect the syncsource idr * @fd_count: Counter for the number of FDs for this process @@ -438,6 +439,7 @@ struct kgsl_process_private { uint64_t cur; uint64_t max; } stats[KGSL_MEM_ENTRY_MAX]; + uint64_t gpumem_mapped; struct idr syncsource_idr; spinlock_t syncsource_lock; int fd_count; diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index 4c54553e9977..fa9b66566004 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -98,6 +98,75 @@ struct mem_entry_stats { static void kgsl_cma_unlock_secure(struct kgsl_memdesc *memdesc); +static ssize_t +imported_mem_show(struct kgsl_process_private *priv, + int type, char *buf) +{ + struct kgsl_mem_entry *entry; + uint64_t imported_mem = 0; + int id = 0; + + spin_lock(&priv->mem_lock); + for (entry = idr_get_next(&priv->mem_idr, &id); entry; + id++, entry = idr_get_next(&priv->mem_idr, &id)) { + + int egl_surface_count = 0, egl_image_count = 0; + struct kgsl_memdesc *m; + + if (kgsl_mem_entry_get(entry) == 0) + continue; + spin_unlock(&priv->mem_lock); + + m = &entry->memdesc; + if (kgsl_memdesc_usermem_type(m) == KGSL_MEM_ENTRY_ION) { + kgsl_get_egl_counts(entry, &egl_surface_count, + &egl_image_count); + + if (kgsl_memdesc_get_memtype(m) == + KGSL_MEMTYPE_EGL_SURFACE) + imported_mem += m->size; + else if (egl_surface_count == 0) { + uint64_t size = m->size; + + do_div(size, (egl_image_count ? + egl_image_count : 1)); + imported_mem += size; + } + } + + kgsl_mem_entry_put(entry); + spin_lock(&priv->mem_lock); + } + spin_unlock(&priv->mem_lock); + + return scnprintf(buf, PAGE_SIZE, "%llu\n", imported_mem); +} + +static ssize_t +gpumem_mapped_show(struct kgsl_process_private *priv, + int type, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%llu\n", + priv->gpumem_mapped); +} + +static ssize_t +gpumem_unmapped_show(struct kgsl_process_private *priv, int type, char *buf) +{ + if (priv->gpumem_mapped > priv->stats[type].cur) + return -EIO; + + return scnprintf(buf, PAGE_SIZE, "%llu\n", + priv->stats[type].cur - priv->gpumem_mapped); +} + +static struct kgsl_mem_entry_attribute debug_memstats[] = { + __MEM_ENTRY_ATTR(0, imported_mem, imported_mem_show), + __MEM_ENTRY_ATTR(0, gpumem_mapped, gpumem_mapped_show), + __MEM_ENTRY_ATTR(KGSL_MEM_ENTRY_KERNEL, gpumem_unmapped, + gpumem_unmapped_show), +}; + /** * Show the current amount of memory allocated for the given memtype */ @@ -220,7 +289,13 @@ void kgsl_process_init_sysfs(struct kgsl_device *device, &mem_stats[i].max_attr.attr)) WARN(1, "Couldn't create sysfs file '%s'\n", mem_stats[i].max_attr.attr.name); + } + for (i = 0; i < ARRAY_SIZE(debug_memstats); i++) { + if (sysfs_create_file(&private->kobj, + &debug_memstats[i].attr)) + WARN(1, "Couldn't create sysfs file '%s'\n", + debug_memstats[i].attr.name); } } From 99a468d26d091dbd974d1e95ddceb9c0e0bfa770 Mon Sep 17 00:00:00 2001 From: Archana Sriram Date: Wed, 17 Oct 2018 11:51:09 +0530 Subject: [PATCH 20/75] msm: kgsl: Correct the state transitions in suspend function GPU should not be forced to SUSPEND state when it is in INIT or NONE state as this transition is invalid. Change-Id: Ia3d0fd131348508fe34c57f271c1f991a98afa19 Signed-off-by: Archana Sriram --- drivers/gpu/msm/kgsl_pwrctrl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index b5476b06176a..b1b0b69d55ba 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -2785,7 +2785,7 @@ static int _suspend(struct kgsl_device *device) if ((device->state == KGSL_STATE_NONE) || (device->state == KGSL_STATE_INIT) || (device->state == KGSL_STATE_SUSPEND)) - goto done; + return ret; /* drain to prevent from more commands being submitted */ device->ftbl->drain(device); @@ -2802,7 +2802,6 @@ static int _suspend(struct kgsl_device *device) if (ret) goto err; -done: kgsl_pwrctrl_set_state(device, KGSL_STATE_SUSPEND); return ret; From 0ec949132a8eaf654362fdc4f07f12fc632e0a08 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Mon, 24 Sep 2018 20:45:53 +0530 Subject: [PATCH 21/75] msm:ipa:Prevent rt rule deletion if rt rule id is invalid Currently RT is deleted even if rt rule or header proc ctx is invalid. Add check to prevent it. Change-Id: Ic37ff9a33fab2b3c0d6393e43452e4b62a91d932 Acked-by: Pooja Kumari Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v2/ipa_rt.c | 23 ++++++++++++++++++++ drivers/platform/msm/ipa/ipa_v3/ipa_rt.c | 27 +++++++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c index 5bab6d0c626a..4fea1255b360 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c @@ -1342,6 +1342,8 @@ int ipa2_reset_rt(enum ipa_ip_type ip, bool user_only) struct ipa_rt_entry *rule_next; struct ipa_rt_tbl_set *rset; u32 apps_start_idx; + struct ipa_hdr_entry *hdr_entry; + struct ipa_hdr_proc_ctx_entry *hdr_proc_entry; int id; bool tbl_user = false; @@ -1395,6 +1397,27 @@ int ipa2_reset_rt(enum ipa_ip_type ip, bool user_only) if (!user_only || rule->ipacm_installed) { list_del(&rule->link); + if (rule->hdr) { + hdr_entry = ipa_id_find( + rule->rule.hdr_hdl); + if (!hdr_entry || + hdr_entry->cookie != IPA_HDR_COOKIE) { + IPAERR_RL( + "Header already deleted\n"); + return -EINVAL; + } + } else if (rule->proc_ctx) { + hdr_proc_entry = + ipa_id_find( + rule->rule.hdr_proc_ctx_hdl); + if (!hdr_proc_entry || + hdr_proc_entry->cookie != + IPA_PROC_HDR_COOKIE) { + IPAERR_RL( + "Proc entry already deleted\n"); + return -EINVAL; + } + } tbl->rule_cnt--; if (rule->hdr) __ipa_release_hdr(rule->hdr->id); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c index 8f6024c51e1d..256843022dfe 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c @@ -1486,6 +1486,8 @@ int ipa3_reset_rt(enum ipa_ip_type ip, bool user_only) struct ipa3_rt_entry *rule; struct ipa3_rt_entry *rule_next; struct ipa3_rt_tbl_set *rset; + struct ipa3_hdr_entry *hdr_entry; + struct ipa3_hdr_proc_ctx_entry *hdr_proc_entry; u32 apps_start_idx; int id; bool tbl_user = false; @@ -1539,6 +1541,27 @@ int ipa3_reset_rt(enum ipa_ip_type ip, bool user_only) if (!user_only || rule->ipacm_installed) { list_del(&rule->link); + if (rule->hdr) { + hdr_entry = ipa3_id_find( + rule->rule.hdr_hdl); + if (!hdr_entry || + hdr_entry->cookie != IPA_HDR_COOKIE) { + IPAERR_RL( + "Header already deleted\n"); + return -EINVAL; + } + } else if (rule->proc_ctx) { + hdr_proc_entry = + ipa3_id_find( + rule->rule.hdr_proc_ctx_hdl); + if (!hdr_proc_entry || + hdr_proc_entry->cookie != + IPA_PROC_HDR_COOKIE) { + IPAERR_RL( + "Proc entry already deleted\n"); + return -EINVAL; + } + } tbl->rule_cnt--; if (rule->hdr) __ipa3_release_hdr(rule->hdr->id); @@ -1546,7 +1569,9 @@ int ipa3_reset_rt(enum ipa_ip_type ip, bool user_only) __ipa3_release_hdr_proc_ctx( rule->proc_ctx->id); rule->cookie = 0; - idr_remove(&tbl->rule_ids, rule->rule_id); + if (!rule->rule_id_valid) + idr_remove(&tbl->rule_ids, + rule->rule_id); id = rule->id; kmem_cache_free(ipa3_ctx->rt_rule_cache, rule); From 9195c4a39f9a68476b68bef46704c3d95b914abb Mon Sep 17 00:00:00 2001 From: Sahitya Tummala Date: Thu, 25 Oct 2018 09:33:54 +0530 Subject: [PATCH 22/75] defconfig: msm: Disable EXT2 and EXT3 FS configs for MSM8998 This is required to fix the VTS test case failures which are failing as the kernel supports EXT2/EXT3 but the tools mkfs.ext2/mkfs.ext3 doesn't exist anymore. Change-Id: I46aa9e9a9c7ebac4655f18fda1451bd2cf594a25 Signed-off-by: Sahitya Tummala --- arch/arm/configs/msmcortex_defconfig | 4 +--- arch/arm64/configs/msmcortex-perf_defconfig | 4 +--- arch/arm64/configs/msmcortex_defconfig | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/arch/arm/configs/msmcortex_defconfig b/arch/arm/configs/msmcortex_defconfig index bb166152c55a..b455e26659bf 100644 --- a/arch/arm/configs/msmcortex_defconfig +++ b/arch/arm/configs/msmcortex_defconfig @@ -484,9 +484,7 @@ CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y CONFIG_MSM_TZ_LOG=y CONFIG_SENSORS_SSC=y -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT3_FS=y +CONFIG_EXT4_FS=y CONFIG_EXT4_FS_SECURITY=y CONFIG_FUSE_FS=y CONFIG_MSDOS_FS=y diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig index 570a21b464ca..8275c554d8a5 100644 --- a/arch/arm64/configs/msmcortex-perf_defconfig +++ b/arch/arm64/configs/msmcortex-perf_defconfig @@ -609,9 +609,7 @@ CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y CONFIG_MSM_TZ_LOG=y CONFIG_SENSORS_SSC=y -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT3_FS=y +CONFIG_EXT4_FS=y CONFIG_EXT4_FS_SECURITY=y CONFIG_EXT4_ENCRYPTION=y CONFIG_EXT4_FS_ENCRYPTION=y diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig index 7015528d0a3c..a4d9ecb59522 100644 --- a/arch/arm64/configs/msmcortex_defconfig +++ b/arch/arm64/configs/msmcortex_defconfig @@ -636,9 +636,7 @@ CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y CONFIG_MSM_TZ_LOG=y CONFIG_SENSORS_SSC=y -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT3_FS=y +CONFIG_EXT4_FS=y CONFIG_EXT4_FS_SECURITY=y CONFIG_EXT4_ENCRYPTION=y CONFIG_EXT4_FS_ENCRYPTION=y From 261ec40f489de816ac478e42f7a9a4702fe70c7e Mon Sep 17 00:00:00 2001 From: Swetha Chikkaboraiah Date: Tue, 23 Oct 2018 17:05:31 +0530 Subject: [PATCH 23/75] ARM: dts: msm: update dload type imem offset for MSM8998 Dload type imem offset is corrected for MSM8998, so that correct imem address is updated. Change-Id: I519603641753ec39d86fbf923bd80afcd6b1345d Signed-off-by: Swetha Chikkaboraiah --- arch/arm/boot/dts/qcom/msm8998.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8998.dtsi b/arch/arm/boot/dts/qcom/msm8998.dtsi index 6990099978c6..7f87a45509e6 100644 --- a/arch/arm/boot/dts/qcom/msm8998.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 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 @@ -2908,9 +2908,9 @@ reg = <0x10 8>; }; - dload_type@18 { + dload_type@1c { compatible = "qcom,msm-imem-dload-type"; - reg = <0x18 4>; + reg = <0x1c 4>; }; restart_reason@65c { From b6e0c36f1c764808f1fa189e906d942df2e30e9d Mon Sep 17 00:00:00 2001 From: Deepak Kumar Date: Wed, 1 Aug 2018 11:57:33 +0530 Subject: [PATCH 24/75] msm: kgsl: Don't halt dispatcher if device is not in SUSPEND state Add a check to make sure device actually transitioned to SUSPEND state before halting dispatcher in adreno_suspend_device function. kgsl_pwrctrl_change_state(device,KGSL_STATE_SUSPEND) in kgsl_suspend_device can return zero without actually changing state to SUSPEND if device state is NONE or INIT. Change-Id: I4a5a69007c71651ea2cf7fa7360c960c6856031e Signed-off-by: Deepak Kumar Signed-off-by: Archana Sriram --- drivers/gpu/msm/adreno.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 9cb65033ed13..d2aa0a0f9507 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -2807,7 +2807,8 @@ static void adreno_suspend_device(struct kgsl_device *device, struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); int pm_event = pm_state.event; - adreno_dispatcher_halt(device); + if (device->state == KGSL_STATE_SUSPEND) + adreno_dispatcher_halt(device); if ((pm_event == PM_EVENT_FREEZE) || (pm_event == PM_EVENT_QUIESCE) || From 15fe99cbf15fef9563cff4dcb716af3aeb5bb6fd Mon Sep 17 00:00:00 2001 From: Sean Tranchetti Date: Fri, 7 Sep 2018 15:50:31 -0600 Subject: [PATCH 25/75] xfrm: validate template mode XFRM mode parameters passed as part of the user templates in the IP_XFRM_POLICY are never properly validated. Passing values other than valid XFRM modes can cause stack-out-of-bounds reads to occur later in the XFRM processing: [ 140.535608] ================================================================ [ 140.543058] BUG: KASAN: stack-out-of-bounds in xfrm_state_find+0x17e4/0x1cc4 [ 140.550306] Read of size 4 at addr ffffffc0238a7a58 by task repro/5148 [ 140.557369] [ 140.558927] Call trace: [ 140.558936] dump_backtrace+0x0/0x388 [ 140.558940] show_stack+0x24/0x30 [ 140.558946] __dump_stack+0x24/0x2c [ 140.558949] dump_stack+0x8c/0xd0 [ 140.558956] print_address_description+0x74/0x234 [ 140.558960] kasan_report+0x240/0x264 [ 140.558963] __asan_report_load4_noabort+0x2c/0x38 [ 140.558967] xfrm_state_find+0x17e4/0x1cc4 [ 140.558971] xfrm_resolve_and_create_bundle+0x40c/0x1fb8 [ 140.558975] xfrm_lookup+0x238/0x1444 [ 140.558977] xfrm_lookup_route+0x48/0x11c [ 140.558984] ip_route_output_flow+0x88/0xc4 [ 140.558991] raw_sendmsg+0xa74/0x266c [ 140.558996] inet_sendmsg+0x258/0x3b0 [ 140.559002] sock_sendmsg+0xbc/0xec [ 140.559005] SyS_sendto+0x3a8/0x5a8 [ 140.559008] el0_svc_naked+0x34/0x38 [ 140.559009] [ 140.592245] page dumped becaus: kasan: bad access detected [ 140.597981] page_owner info is not active (free page?) [ 140.603267] [ 140.653503] ================================================================ Change-Id: I5d2fa78a9d950c79d83d759bfd4d0f399fed18a4 Signed-off-by: Sean Tranchetti --- net/xfrm/xfrm_user.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 8efc7c39275d..081935f8cf52 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1402,6 +1402,9 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) (ut[i].family != prev_family)) return -EINVAL; + if (ut[i].mode >= XFRM_MODE_MAX) + return -EINVAL; + prev_family = ut[i].family; switch (ut[i].family) { From b97feb8274eb5604f3913ecbddeab3cec82193c0 Mon Sep 17 00:00:00 2001 From: Yuanyuan Liu Date: Fri, 5 Oct 2018 15:03:13 -0700 Subject: [PATCH 26/75] icnss: NULL terminate the fw build timestamp string If fw build timestamp passed by QMI is a non-NULL terminated string, it might result in a out-of-bounds read in icnss_get_soc_info. Hence, manually NULL terminate the string. Change-Id: I252196cd12784d841b29303c42591efc59da64f1 CRs-Fixed: 2322317 Signed-off-by: Yuanyuan Liu --- drivers/soc/qcom/icnss.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index 7eb7221835d4..e0fa8b7720d2 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -3035,6 +3035,8 @@ EXPORT_SYMBOL(icnss_disable_irq); int icnss_get_soc_info(struct device *dev, struct icnss_soc_info *info) { + char *fw_build_timestamp = NULL; + if (!penv || !dev) { icnss_pr_err("Platform driver not initialized\n"); return -EINVAL; @@ -3047,6 +3049,8 @@ int icnss_get_soc_info(struct device *dev, struct icnss_soc_info *info) info->board_id = penv->board_info.board_id; info->soc_id = penv->soc_info.soc_id; info->fw_version = penv->fw_version_info.fw_version; + fw_build_timestamp = penv->fw_version_info.fw_build_timestamp; + fw_build_timestamp[QMI_WLFW_MAX_TIMESTAMP_LEN_V01] = '\0'; strlcpy(info->fw_build_timestamp, penv->fw_version_info.fw_build_timestamp, QMI_WLFW_MAX_TIMESTAMP_LEN_V01 + 1); From dcd2081a8a567808c96b0d50d0e055c8d815fe00 Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Wed, 10 Oct 2018 17:01:17 +0800 Subject: [PATCH 27/75] coresight: fix handling of ETM management register access via sysfs This patch add a coresight unit specific function coresight_cross_read which can be used for ETM registers by providing a ETM specific read function which does smp cross call to ensure the unit is powered up before the register is accessed. Change-Id: I4037028a171c8ca733513e82c4443b6e332a088c Signed-off-by: Yuanfang Zhang --- drivers/hwtracing/coresight/coresight-etm4x.c | 82 +++++++++++++------ 1 file changed, 59 insertions(+), 23 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 9f9dd574c8d0..6bd4c8979960 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -2196,6 +2196,42 @@ static struct attribute *coresight_etmv4_attrs[] = { NULL, }; +struct etmv4_reg { + void __iomem *addr; + u32 data; +}; + +static void do_smp_cross_read(void *data) +{ + struct etmv4_reg *reg = data; + + reg->data = readl_relaxed(reg->addr); +} + +static u32 etmv4_cross_read(const struct device *dev, u32 offset) +{ + struct etmv4_drvdata *drvdata = dev_get_drvdata(dev); + struct etmv4_reg reg; + + reg.addr = drvdata->base + offset; + + smp_call_function_single(drvdata->cpu, do_smp_cross_read, ®, 1); + return reg.data; +} +#define coresight_cross_read(name, offset) \ +static ssize_t name##_show(struct device *_dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + u32 val; \ + pm_runtime_get_sync(_dev->parent); \ + \ + val = etmv4_cross_read(_dev->parent, offset); \ + \ + pm_runtime_put_sync(_dev->parent); \ + return scnprintf(buf, PAGE_SIZE, "0x%x\n", val); \ +} \ +static DEVICE_ATTR_RO(name) + #define coresight_simple_func(name, offset) \ static ssize_t name##_show(struct device *_dev, \ struct device_attribute *attr, char *buf) \ @@ -2206,17 +2242,17 @@ static ssize_t name##_show(struct device *_dev, \ } \ DEVICE_ATTR_RO(name) -coresight_simple_func(trcoslsr, TRCOSLSR); -coresight_simple_func(trcpdcr, TRCPDCR); -coresight_simple_func(trcpdsr, TRCPDSR); -coresight_simple_func(trclsr, TRCLSR); -coresight_simple_func(trcauthstatus, TRCAUTHSTATUS); -coresight_simple_func(trcdevid, TRCDEVID); -coresight_simple_func(trcdevtype, TRCDEVTYPE); -coresight_simple_func(trcpidr0, TRCPIDR0); -coresight_simple_func(trcpidr1, TRCPIDR1); -coresight_simple_func(trcpidr2, TRCPIDR2); -coresight_simple_func(trcpidr3, TRCPIDR3); +coresight_cross_read(trcoslsr, TRCOSLSR); +coresight_cross_read(trcpdcr, TRCPDCR); +coresight_cross_read(trcpdsr, TRCPDSR); +coresight_cross_read(trclsr, TRCLSR); +coresight_cross_read(trcauthstatus, TRCAUTHSTATUS); +coresight_cross_read(trcdevid, TRCDEVID); +coresight_cross_read(trcdevtype, TRCDEVTYPE); +coresight_cross_read(trcpidr0, TRCPIDR0); +coresight_cross_read(trcpidr1, TRCPIDR1); +coresight_cross_read(trcpidr2, TRCPIDR2); +coresight_cross_read(trcpidr3, TRCPIDR3); static struct attribute *coresight_etmv4_mgmt_attrs[] = { &dev_attr_trcoslsr.attr, @@ -2233,19 +2269,19 @@ static struct attribute *coresight_etmv4_mgmt_attrs[] = { NULL, }; -coresight_simple_func(trcidr0, TRCIDR0); -coresight_simple_func(trcidr1, TRCIDR1); -coresight_simple_func(trcidr2, TRCIDR2); -coresight_simple_func(trcidr3, TRCIDR3); -coresight_simple_func(trcidr4, TRCIDR4); -coresight_simple_func(trcidr5, TRCIDR5); +coresight_cross_read(trcidr0, TRCIDR0); +coresight_cross_read(trcidr1, TRCIDR1); +coresight_cross_read(trcidr2, TRCIDR2); +coresight_cross_read(trcidr3, TRCIDR3); +coresight_cross_read(trcidr4, TRCIDR4); +coresight_cross_read(trcidr5, TRCIDR5); /* trcidr[6,7] are reserved */ -coresight_simple_func(trcidr8, TRCIDR8); -coresight_simple_func(trcidr9, TRCIDR9); -coresight_simple_func(trcidr10, TRCIDR10); -coresight_simple_func(trcidr11, TRCIDR11); -coresight_simple_func(trcidr12, TRCIDR12); -coresight_simple_func(trcidr13, TRCIDR13); +coresight_cross_read(trcidr8, TRCIDR8); +coresight_cross_read(trcidr9, TRCIDR9); +coresight_cross_read(trcidr10, TRCIDR10); +coresight_cross_read(trcidr11, TRCIDR11); +coresight_cross_read(trcidr12, TRCIDR12); +coresight_cross_read(trcidr13, TRCIDR13); static struct attribute *coresight_etmv4_trcidr_attrs[] = { &dev_attr_trcidr0.attr, From 25611b44f1efba8a7c3cbbf72c9387313f96906c Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Mon, 8 Oct 2018 20:04:48 +0530 Subject: [PATCH 28/75] msm: ipa3: Fix to validate the user inputs Adding code changes to validate user inputs. Before allocating the NAT entry verifying the NAT entry size in range or not. Change-Id: I21147f20a12243af5d21aebdc206703964db2be4 Acked-by: Ashok Vuyyuru Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v2/ipa_nat.c | 14 ++++++++++++++ drivers/platform/msm/ipa/ipa_v3/ipa_nat.c | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c index 7cddbf850540..a7cdf691ec68 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c @@ -35,6 +35,13 @@ enum nat_table_type { #define NAT_TABLE_ENTRY_SIZE_BYTE 32 #define NAT_INTEX_TABLE_ENTRY_SIZE_BYTE 4 +/* + * Max NAT table entries is limited 1000 entries. + * Limit the memory size required by user to prevent kernel memory starvation + */ +#define IPA_TABLE_MAX_ENTRIES 1000 +#define MAX_ALLOC_NAT_SIZE (IPA_TABLE_MAX_ENTRIES * NAT_TABLE_ENTRY_SIZE_BYTE) + static int ipa_nat_vma_fault_remap( struct vm_area_struct *vma, struct vm_fault *vmf) { @@ -270,6 +277,13 @@ int ipa2_allocate_nat_device(struct ipa_ioc_nat_alloc_mem *mem) goto bail; } + if (mem->size > MAX_ALLOC_NAT_SIZE) { + IPAERR("Trying allocate more size = %zu, Max allowed = %d\n", + mem->size, MAX_ALLOC_NAT_SIZE); + result = -EPERM; + goto bail; + } + if (mem->size <= 0 || nat_ctx->is_dev_init == true) { IPAERR_RL("Invalid Parameters or device is already init\n"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c index 17e4cae311ce..0b52acdeafc1 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c @@ -34,6 +34,13 @@ enum nat_table_type { #define NAT_TABLE_ENTRY_SIZE_BYTE 32 #define NAT_INTEX_TABLE_ENTRY_SIZE_BYTE 4 +/* + * Max NAT table entries is limited 1000 entries. + * Limit the memory size required by user to prevent kernel memory starvation + */ +#define IPA_TABLE_MAX_ENTRIES 1000 +#define MAX_ALLOC_NAT_SIZE (IPA_TABLE_MAX_ENTRIES * NAT_TABLE_ENTRY_SIZE_BYTE) + static int ipa3_nat_vma_fault_remap( struct vm_area_struct *vma, struct vm_fault *vmf) { @@ -272,6 +279,13 @@ int ipa3_allocate_nat_device(struct ipa_ioc_nat_alloc_mem *mem) goto bail; } + if (mem->size > MAX_ALLOC_NAT_SIZE) { + IPAERR("Trying allocate more size = %zu, Max allowed = %d\n", + mem->size, MAX_ALLOC_NAT_SIZE); + result = -EPERM; + goto bail; + } + if (mem->size <= 0 || nat_ctx->is_dev_init == true) { IPAERR_RL("Invalid Parameters or device is already init\n"); From e31c601552bba006d4e1a32d59dc2e43db9c31d9 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Mon, 8 Oct 2018 20:04:48 +0530 Subject: [PATCH 29/75] msm: ipa3: Fix to validate the user inputs Adding code changes to validate user inputs. Before allocating the NAT entry verifying the NAT entry size in range or not. Change-Id: I21147f20a12243af5d21aebdc206703964db2be4 Acked-by: Ashok Vuyyuru Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v2/ipa_nat.c | 14 ++++++++++++++ drivers/platform/msm/ipa/ipa_v3/ipa_nat.c | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c index 7cddbf850540..a7cdf691ec68 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c @@ -35,6 +35,13 @@ enum nat_table_type { #define NAT_TABLE_ENTRY_SIZE_BYTE 32 #define NAT_INTEX_TABLE_ENTRY_SIZE_BYTE 4 +/* + * Max NAT table entries is limited 1000 entries. + * Limit the memory size required by user to prevent kernel memory starvation + */ +#define IPA_TABLE_MAX_ENTRIES 1000 +#define MAX_ALLOC_NAT_SIZE (IPA_TABLE_MAX_ENTRIES * NAT_TABLE_ENTRY_SIZE_BYTE) + static int ipa_nat_vma_fault_remap( struct vm_area_struct *vma, struct vm_fault *vmf) { @@ -270,6 +277,13 @@ int ipa2_allocate_nat_device(struct ipa_ioc_nat_alloc_mem *mem) goto bail; } + if (mem->size > MAX_ALLOC_NAT_SIZE) { + IPAERR("Trying allocate more size = %zu, Max allowed = %d\n", + mem->size, MAX_ALLOC_NAT_SIZE); + result = -EPERM; + goto bail; + } + if (mem->size <= 0 || nat_ctx->is_dev_init == true) { IPAERR_RL("Invalid Parameters or device is already init\n"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c index 17e4cae311ce..0b52acdeafc1 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c @@ -34,6 +34,13 @@ enum nat_table_type { #define NAT_TABLE_ENTRY_SIZE_BYTE 32 #define NAT_INTEX_TABLE_ENTRY_SIZE_BYTE 4 +/* + * Max NAT table entries is limited 1000 entries. + * Limit the memory size required by user to prevent kernel memory starvation + */ +#define IPA_TABLE_MAX_ENTRIES 1000 +#define MAX_ALLOC_NAT_SIZE (IPA_TABLE_MAX_ENTRIES * NAT_TABLE_ENTRY_SIZE_BYTE) + static int ipa3_nat_vma_fault_remap( struct vm_area_struct *vma, struct vm_fault *vmf) { @@ -272,6 +279,13 @@ int ipa3_allocate_nat_device(struct ipa_ioc_nat_alloc_mem *mem) goto bail; } + if (mem->size > MAX_ALLOC_NAT_SIZE) { + IPAERR("Trying allocate more size = %zu, Max allowed = %d\n", + mem->size, MAX_ALLOC_NAT_SIZE); + result = -EPERM; + goto bail; + } + if (mem->size <= 0 || nat_ctx->is_dev_init == true) { IPAERR_RL("Invalid Parameters or device is already init\n"); From b8cab6d1758febbac9ca39b4da42e6c556e92428 Mon Sep 17 00:00:00 2001 From: "Isaac J. Manjarres" Date: Tue, 4 Sep 2018 09:38:58 -0700 Subject: [PATCH 30/75] soc: qcom: service-locator: Free PD list after client use Currently, when a client invokes the service-locator to get the domain list for a service, a data structure is dynamically allocated to hold this information, and that is given to the client for use. However, after the client uses the domain list, the data structure is not freed, resulting in a memory leak. Free domain list data structure after client use to fix memory leak. Change-Id: I2b87afefbb35c2c296b4267450fa3152e3725ab9 Signed-off-by: Isaac J. Manjarres --- drivers/soc/qcom/service-locator.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c index 52355699e4f3..f6146d9009bc 100644 --- a/drivers/soc/qcom/service-locator.c +++ b/drivers/soc/qcom/service-locator.c @@ -251,7 +251,6 @@ static int service_locator_send_msg(struct pd_qmi_client_data *pd) req->domain_offset_valid = true; req->domain_offset = 0; - pd->domain_list = NULL; do { req->domain_offset += domains_read; rc = servreg_loc_send_msg(&req_desc, &resp_desc, req, resp, @@ -281,6 +280,7 @@ static int service_locator_send_msg(struct pd_qmi_client_data *pd) pr_err("Service Locator DB updated for client %s\n", pd->client_name); kfree(pd->domain_list); + pd->domain_list = NULL; rc = -EAGAIN; goto out; } @@ -360,7 +360,7 @@ int get_service_location(char *client_name, char *service_name, goto err; } - pqcd = kmalloc(sizeof(struct pd_qmi_client_data), GFP_KERNEL); + pqcd = kzalloc(sizeof(struct pd_qmi_client_data), GFP_KERNEL); if (!pqcd) { rc = -ENOMEM; pr_err("Allocation failed\n"); @@ -401,7 +401,7 @@ static void pd_locator_work(struct work_struct *work) pr_err("Unable to connect to service locator!, rc = %d\n", rc); pdqw->notifier->notifier_call(pdqw->notifier, LOCATOR_DOWN, NULL); - goto err; + goto err_init_servloc; } rc = service_locator_send_msg(data); if (rc) { @@ -409,11 +409,13 @@ static void pd_locator_work(struct work_struct *work) data->service_name, data->client_name, rc); pdqw->notifier->notifier_call(pdqw->notifier, LOCATOR_DOWN, NULL); - goto err; + goto err_servloc_send_msg; } pdqw->notifier->notifier_call(pdqw->notifier, LOCATOR_UP, data); -err: +err_servloc_send_msg: + kfree(data->domain_list); +err_init_servloc: kfree(data); kfree(pdqw); } From e10ca47f4b9c09231e8068e5cd25016a4db92b85 Mon Sep 17 00:00:00 2001 From: Hardik Arya Date: Wed, 10 Oct 2018 18:25:49 +0530 Subject: [PATCH 31/75] soc: qcom: Remove smp2p test support Smp2p test code is used internally to test the functionality of drivers and has no real use case in end product. Change-Id: I7a50c077bb71068188b5411424c5782b3d0edbb7 Signed-off-by: Hardik Arya --- drivers/gpio/Makefile | 1 - drivers/gpio/gpio-msm-smp2p-test.c | 762 -------------- drivers/soc/qcom/Makefile | 3 +- drivers/soc/qcom/smp2p_spinlock_test.c | 819 --------------- drivers/soc/qcom/smp2p_test.c | 1327 ------------------------ drivers/soc/qcom/smp2p_test_common.h | 214 ---- 6 files changed, 1 insertion(+), 3125 deletions(-) delete mode 100644 drivers/gpio/gpio-msm-smp2p-test.c delete mode 100644 drivers/soc/qcom/smp2p_spinlock_test.c delete mode 100644 drivers/soc/qcom/smp2p_test.c delete mode 100644 drivers/soc/qcom/smp2p_test_common.h diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ac55dd34cfcb..7f2acfabf86d 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -121,4 +121,3 @@ obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o obj-$(CONFIG_GPIO_ZX) += gpio-zx.o obj-$(CONFIG_MSM_SMP2P) += gpio-msm-smp2p.o -obj-$(CONFIG_MSM_SMP2P_TEST) += gpio-msm-smp2p-test.o diff --git a/drivers/gpio/gpio-msm-smp2p-test.c b/drivers/gpio/gpio-msm-smp2p-test.c deleted file mode 100644 index 5907513b43c0..000000000000 --- a/drivers/gpio/gpio-msm-smp2p-test.c +++ /dev/null @@ -1,762 +0,0 @@ -/* drivers/gpio/gpio-msm-smp2p-test.c - * - * 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 - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../soc/qcom/smp2p_private.h" -#include "../soc/qcom/smp2p_test_common.h" - -/* Interrupt callback data */ -struct gpio_info { - int gpio_base_id; - int irq_base_id; - - bool initialized; - struct completion cb_completion; - int cb_count; - DECLARE_BITMAP(triggered_irqs, SMP2P_BITS_PER_ENTRY); -}; - -/* GPIO Inbound/Outbound callback info */ -struct gpio_inout { - struct gpio_info in; - struct gpio_info out; -}; - -static struct gpio_inout gpio_info[SMP2P_NUM_PROCS]; - -/** - * Init/reset the callback data. - * - * @info: Pointer to callback data - */ -static void cb_data_reset(struct gpio_info *info) -{ - int n; - - if (!info) - return; - - if (!info->initialized) { - init_completion(&info->cb_completion); - info->initialized = true; - } - info->cb_count = 0; - - for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) - clear_bit(n, info->triggered_irqs); - - reinit_completion(&info->cb_completion); -} - -static int smp2p_gpio_test_probe(struct platform_device *pdev) -{ - int id; - int cnt; - struct device_node *node = pdev->dev.of_node; - struct gpio_info *gpio_info_ptr = NULL; - - /* - * NOTE: This does a string-lookup of the GPIO pin name and doesn't - * actually directly link to the SMP2P GPIO driver since all - * GPIO/Interrupt access must be through standard - * Linux GPIO / Interrupt APIs. - */ - if (strcmp("qcom,smp2pgpio_test_smp2p_1_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_MODEM_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_1_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_MODEM_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_2_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_AUDIO_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_2_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_AUDIO_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_3_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_SENSOR_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_3_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_SENSOR_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_4_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_WIRELESS_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_4_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_WIRELESS_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_5_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_CDSP_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_5_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_CDSP_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_7_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_TZ_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_7_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_TZ_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_15_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in; - } else if ( - strcmp("qcom,smp2pgpio_test_smp2p_15_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_REMOTE_MOCK_PROC].out; - } else { - pr_err("%s: unable to match device type '%s'\n", - __func__, node->name); - return -ENODEV; - } - - /* retrieve the GPIO and interrupt ID's */ - cnt = of_gpio_count(node); - if (cnt && gpio_info_ptr) { - /* - * Instead of looping through all 32-bits, we can just get the - * first pin to get the base IDs. This saves on the verbosity - * of the device tree nodes as well. - */ - id = of_get_gpio(node, 0); - if (id == -EPROBE_DEFER) - return id; - gpio_info_ptr->gpio_base_id = id; - gpio_info_ptr->irq_base_id = gpio_to_irq(id); - } - return 0; -} - -/* - * NOTE: Instead of match table and device driver, you may be able to just - * call of_find_compatible_node() in your init function. - */ -static struct of_device_id msm_smp2p_match_table[] = { - /* modem */ - {.compatible = "qcom,smp2pgpio_test_smp2p_1_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_1_in", }, - - /* audio (adsp) */ - {.compatible = "qcom,smp2pgpio_test_smp2p_2_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_2_in", }, - - /* sensor */ - {.compatible = "qcom,smp2pgpio_test_smp2p_3_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_3_in", }, - - /* wcnss */ - {.compatible = "qcom,smp2pgpio_test_smp2p_4_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_4_in", }, - - /* CDSP */ - {.compatible = "qcom,smp2pgpio_test_smp2p_5_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_5_in", }, - - /* TZ */ - {.compatible = "qcom,smp2pgpio_test_smp2p_7_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_7_in", }, - - /* mock loopback */ - {.compatible = "qcom,smp2pgpio_test_smp2p_15_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_15_in", }, - {}, -}; - -static struct platform_driver smp2p_gpio_driver = { - .probe = smp2p_gpio_test_probe, - .driver = { - .name = "smp2pgpio_test", - .owner = THIS_MODULE, - .of_match_table = msm_smp2p_match_table, - }, -}; - -/** - * smp2p_ut_local_gpio_out - Verify outbound functionality. - * - * @s: pointer to output file - */ -static void smp2p_ut_local_gpio_out(struct seq_file *s) -{ - int failed = 0; - struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].out; - int ret; - int id; - struct msm_smp2p_remote_mock *mock; - - seq_printf(s, "Running %s\n", __func__); - do { - /* initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - mock = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(mock, !=, NULL); - - mock->rx_interrupt_count = 0; - memset(&mock->remote_item, 0, - sizeof(struct smp2p_smem_item)); - smp2p_init_header((struct smp2p_smem *)&mock->remote_item, - SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC, - 0, 1); - strlcpy(mock->remote_item.entries[0].name, "smp2p", - SMP2P_MAX_ENTRY_NAME); - SMP2P_SET_ENT_VALID( - mock->remote_item.header.valid_total_ent, 1); - msm_smp2p_set_remote_mock_exists(true); - mock->tx_interrupt(); - - /* open GPIO entry */ - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, true); - - /* verify set/get functions */ - UT_ASSERT_INT(0, <, cb_info->gpio_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - int pin = cb_info->gpio_base_id + id; - - mock->rx_interrupt_count = 0; - gpio_set_value(pin, 1); - UT_ASSERT_INT(1, ==, mock->rx_interrupt_count); - UT_ASSERT_INT(1, ==, gpio_get_value(pin)); - - gpio_set_value(pin, 0); - UT_ASSERT_INT(2, ==, mock->rx_interrupt_count); - UT_ASSERT_INT(0, ==, gpio_get_value(pin)); - } - if (failed) - break; - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } - - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, false); -} - -/** - * smp2p_gpio_irq - Interrupt handler for inbound entries. - * - * @irq: Virtual IRQ being triggered - * @data: Cookie data (struct gpio_info * in this case) - * @returns: Number of bytes written - */ -static irqreturn_t smp2p_gpio_irq(int irq, void *data) -{ - struct gpio_info *gpio_ptr = (struct gpio_info *)data; - int offset; - - if (!gpio_ptr) { - pr_err("%s: gpio_ptr is NULL for irq %d\n", __func__, irq); - return IRQ_HANDLED; - } - - offset = irq - gpio_ptr->irq_base_id; - if (offset >= 0 && offset < SMP2P_BITS_PER_ENTRY) - set_bit(offset, gpio_ptr->triggered_irqs); - else - pr_err("%s: invalid irq offset base %d; irq %d\n", - __func__, gpio_ptr->irq_base_id, irq); - - ++gpio_ptr->cb_count; - complete(&gpio_ptr->cb_completion); - return IRQ_HANDLED; -} - -/** - * smp2p_ut_local_gpio_in - Verify inbound functionality. - * - * @s: pointer to output file - */ -static void smp2p_ut_local_gpio_in(struct seq_file *s) -{ - int failed = 0; - struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in; - int id; - int ret; - int virq; - struct msm_smp2p_remote_mock *mock; - - seq_printf(s, "Running %s\n", __func__); - - cb_data_reset(cb_info); - do { - /* initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - mock = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(mock, !=, NULL); - - mock->rx_interrupt_count = 0; - memset(&mock->remote_item, 0, - sizeof(struct smp2p_smem_item)); - smp2p_init_header((struct smp2p_smem *)&mock->remote_item, - SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC, - 0, 1); - strlcpy(mock->remote_item.entries[0].name, "smp2p", - SMP2P_MAX_ENTRY_NAME); - SMP2P_SET_ENT_VALID( - mock->remote_item.header.valid_total_ent, 1); - msm_smp2p_set_remote_mock_exists(true); - mock->tx_interrupt(); - - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, true); - - /* verify set/get functions locally */ - UT_ASSERT_INT(0, <, cb_info->gpio_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - int pin; - int current_value; - - /* verify pin value cannot be set */ - pin = cb_info->gpio_base_id + id; - current_value = gpio_get_value(pin); - - gpio_set_value(pin, 0); - UT_ASSERT_INT(current_value, ==, gpio_get_value(pin)); - gpio_set_value(pin, 1); - UT_ASSERT_INT(current_value, ==, gpio_get_value(pin)); - - /* verify no interrupts */ - UT_ASSERT_INT(0, ==, cb_info->cb_count); - } - if (failed) - break; - - /* register for interrupts */ - UT_ASSERT_INT(0, <, cb_info->irq_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq)); - ret = request_irq(virq, - smp2p_gpio_irq, IRQF_TRIGGER_RISING, - "smp2p_test", cb_info); - UT_ASSERT_INT(0, ==, ret); - } - if (failed) - break; - - /* verify both rising and falling edge interrupts */ - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - irq_set_irq_type(virq, IRQ_TYPE_EDGE_BOTH); - cb_data_reset(cb_info); - - /* verify rising-edge interrupt */ - mock->remote_item.entries[0].entry = 1 << id; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 1); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - test_bit(id, cb_info->triggered_irqs); - - /* verify falling-edge interrupt */ - mock->remote_item.entries[0].entry = 0; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 2); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - } - if (failed) - break; - - /* verify rising-edge interrupts */ - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING); - cb_data_reset(cb_info); - - /* verify only rising-edge interrupt is triggered */ - mock->remote_item.entries[0].entry = 1 << id; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 1); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - test_bit(id, cb_info->triggered_irqs); - - mock->remote_item.entries[0].entry = 0; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 1); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - } - if (failed) - break; - - /* verify falling-edge interrupts */ - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - irq_set_irq_type(virq, IRQ_TYPE_EDGE_FALLING); - cb_data_reset(cb_info); - - /* verify only rising-edge interrupt is triggered */ - mock->remote_item.entries[0].entry = 1 << id; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 0); - UT_ASSERT_INT(0, ==, - test_bit(id, cb_info->triggered_irqs)); - - mock->remote_item.entries[0].entry = 0; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 1); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - } - if (failed) - break; - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } - - /* unregister for interrupts */ - if (cb_info->irq_base_id) { - for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id) - free_irq(cb_info->irq_base_id + id, cb_info); - } - - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, false); -} - -/** - * smp2p_ut_local_gpio_in_update_open - Verify combined open/update. - * - * @s: pointer to output file - * - * If the remote side updates the SMP2P bits and sends before negotiation is - * complete, then the UPDATE event will have to be delayed until negotiation is - * complete. This should result in both the OPEN and UPDATE events coming in - * right after each other and the behavior should be transparent to the clients - * of SMP2P GPIO. - */ -static void smp2p_ut_local_gpio_in_update_open(struct seq_file *s) -{ - int failed = 0; - struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in; - int id; - int ret; - int virq; - struct msm_smp2p_remote_mock *mock; - - seq_printf(s, "Running %s\n", __func__); - - cb_data_reset(cb_info); - do { - /* initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - mock = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(mock, !=, NULL); - - mock->rx_interrupt_count = 0; - memset(&mock->remote_item, 0, - sizeof(struct smp2p_smem_item)); - smp2p_init_header((struct smp2p_smem *)&mock->remote_item, - SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC, - 0, 1); - strlcpy(mock->remote_item.entries[0].name, "smp2p", - SMP2P_MAX_ENTRY_NAME); - SMP2P_SET_ENT_VALID( - mock->remote_item.header.valid_total_ent, 1); - - /* register for interrupts */ - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, true); - - UT_ASSERT_INT(0, <, cb_info->irq_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq)); - ret = request_irq(virq, - smp2p_gpio_irq, IRQ_TYPE_EDGE_BOTH, - "smp2p_test", cb_info); - UT_ASSERT_INT(0, ==, ret); - } - if (failed) - break; - - /* update the state value and complete negotiation */ - mock->remote_item.entries[0].entry = 0xDEADDEAD; - msm_smp2p_set_remote_mock_exists(true); - mock->tx_interrupt(); - - /* verify delayed state updates were processed */ - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - - UT_ASSERT_INT(cb_info->cb_count, >, 0); - if (0x1 & (0xDEADDEAD >> id)) { - /* rising edge should have been triggered */ - if (!test_bit(id, cb_info->triggered_irqs)) { - seq_printf(s, "%s:%d bit %d clear, ", - __func__, __LINE__, id); - seq_puts(s, "expected set\n"); - failed = 1; - break; - } - } else { - /* edge should not have been triggered */ - if (test_bit(id, cb_info->triggered_irqs)) { - seq_printf(s, "%s:%d bit %d set, ", - __func__, __LINE__, id); - seq_puts(s, "expected clear\n"); - failed = 1; - break; - } - } - } - if (failed) - break; - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } - - /* unregister for interrupts */ - if (cb_info->irq_base_id) { - for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id) - free_irq(cb_info->irq_base_id + id, cb_info); - } - - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, false); -} - -/** - * smp2p_gpio_write_bits - writes value to each GPIO pin specified in mask. - * - * @gpio: gpio test structure - * @mask: 1 = write gpio_value to this GPIO pin - * @gpio_value: value to write to GPIO pin - */ -static void smp2p_gpio_write_bits(struct gpio_info *gpio, uint32_t mask, - int gpio_value) -{ - int n; - - for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) { - if (mask & 0x1) - gpio_set_value(gpio->gpio_base_id + n, gpio_value); - mask >>= 1; - } -} - -static void smp2p_gpio_set_bits(struct gpio_info *gpio, uint32_t mask) -{ - smp2p_gpio_write_bits(gpio, mask, 1); -} - -static void smp2p_gpio_clr_bits(struct gpio_info *gpio, uint32_t mask) -{ - smp2p_gpio_write_bits(gpio, mask, 0); -} - -/** - * smp2p_gpio_get_value - reads entire 32-bits of GPIO - * - * @gpio: gpio structure - * @returns: 32 bit value of GPIO pins - */ -static uint32_t smp2p_gpio_get_value(struct gpio_info *gpio) -{ - int n; - uint32_t value = 0; - - for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) { - if (gpio_get_value(gpio->gpio_base_id + n)) - value |= 1 << n; - } - return value; -} - -/** - * smp2p_ut_remote_inout_core - Verify inbound/outbound functionality. - * - * @s: pointer to output file - * @remote_pid: Remote processor to test - * @name: Name of the test for reporting - * - * This test verifies inbound/outbound functionality for the remote processor. - */ -static void smp2p_ut_remote_inout_core(struct seq_file *s, int remote_pid, - const char *name) -{ - int failed = 0; - uint32_t request; - uint32_t response; - struct gpio_info *cb_in; - struct gpio_info *cb_out; - int id; - int ret; - - seq_printf(s, "Running %s for '%s' remote pid %d\n", - __func__, smp2p_pid_to_name(remote_pid), remote_pid); - - cb_in = &gpio_info[remote_pid].in; - cb_out = &gpio_info[remote_pid].out; - cb_data_reset(cb_in); - cb_data_reset(cb_out); - do { - /* open test entries */ - msm_smp2p_deinit_rmt_lpb_proc(remote_pid); - smp2p_gpio_open_test_entry("smp2p", remote_pid, true); - - /* register for interrupts */ - UT_ASSERT_INT(0, <, cb_in->gpio_base_id); - UT_ASSERT_INT(0, <, cb_in->irq_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - int virq = cb_in->irq_base_id + id; - UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq)); - ret = request_irq(virq, - smp2p_gpio_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "smp2p_test", cb_in); - UT_ASSERT_INT(0, ==, ret); - } - if (failed) - break; - - /* write echo of data value 0 */ - UT_ASSERT_INT(0, <, cb_out->gpio_base_id); - request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(request, 1); - SMP2P_SET_RMT_CMD(request, SMP2P_LB_CMD_ECHO); - SMP2P_SET_RMT_DATA(request, 0x0); - - smp2p_gpio_set_bits(cb_out, SMP2P_RMT_IGNORE_MASK); - smp2p_gpio_clr_bits(cb_out, ~SMP2P_RMT_IGNORE_MASK); - smp2p_gpio_set_bits(cb_out, request); - - UT_ASSERT_INT(cb_in->cb_count, ==, 0); - smp2p_gpio_clr_bits(cb_out, SMP2P_RMT_IGNORE_MASK); - - /* verify response */ - do { - /* wait for up to 32 changes */ - if (wait_for_completion_timeout( - &cb_in->cb_completion, HZ / 2) == 0) - break; - reinit_completion(&cb_in->cb_completion); - } while (cb_in->cb_count < 32); - UT_ASSERT_INT(cb_in->cb_count, >, 0); - response = smp2p_gpio_get_value(cb_in); - SMP2P_SET_RMT_CMD_TYPE(request, 0); - UT_ASSERT_HEX(request, ==, response); - - /* write echo of data value of all 1's */ - request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(request, 1); - SMP2P_SET_RMT_CMD(request, SMP2P_LB_CMD_ECHO); - SMP2P_SET_RMT_DATA(request, ~0); - - smp2p_gpio_set_bits(cb_out, SMP2P_RMT_IGNORE_MASK); - cb_data_reset(cb_in); - smp2p_gpio_clr_bits(cb_out, ~SMP2P_RMT_IGNORE_MASK); - smp2p_gpio_set_bits(cb_out, request); - - UT_ASSERT_INT(cb_in->cb_count, ==, 0); - smp2p_gpio_clr_bits(cb_out, SMP2P_RMT_IGNORE_MASK); - - /* verify response including 24 interrupts */ - do { - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in->cb_completion, HZ / 2), - >, 0); - reinit_completion(&cb_in->cb_completion); - } while (cb_in->cb_count < 24); - response = smp2p_gpio_get_value(cb_in); - SMP2P_SET_RMT_CMD_TYPE(request, 0); - UT_ASSERT_HEX(request, ==, response); - UT_ASSERT_INT(24, ==, cb_in->cb_count); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", name); - seq_puts(s, "\tFailed\n"); - } - - /* unregister for interrupts */ - if (cb_in->irq_base_id) { - for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id) - free_irq(cb_in->irq_base_id + id, cb_in); - } - - smp2p_gpio_open_test_entry("smp2p", remote_pid, false); - msm_smp2p_init_rmt_lpb_proc(remote_pid); -} - -/** - * smp2p_ut_remote_inout - Verify inbound/outbound functionality for all. - * - * @s: pointer to output file - * - * This test verifies inbound and outbound functionality for all - * configured remote processor. - */ -static void smp2p_ut_remote_inout(struct seq_file *s) -{ - struct smp2p_interrupt_config *int_cfg; - int pid; - - int_cfg = smp2p_get_interrupt_config(); - if (!int_cfg) { - seq_puts(s, "Remote processor config unavailable\n"); - return; - } - - for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) { - if (!int_cfg[pid].is_configured) - continue; - - smp2p_ut_remote_inout_core(s, pid, __func__); - } -} - -static int __init smp2p_debugfs_init(void) -{ - /* register GPIO pins */ - (void)platform_driver_register(&smp2p_gpio_driver); - - /* - * Add Unit Test entries. - * - * The idea with unit tests is that you can run all of them - * from ADB shell by doing: - * adb shell - * cat ut* - * - * And if particular tests fail, you can then repeatedly run the - * failing tests as you debug and resolve the failing test. - */ - smp2p_debug_create("ut_local_gpio_out", smp2p_ut_local_gpio_out); - smp2p_debug_create("ut_local_gpio_in", smp2p_ut_local_gpio_in); - smp2p_debug_create("ut_local_gpio_in_update_open", - smp2p_ut_local_gpio_in_update_open); - smp2p_debug_create("ut_remote_gpio_inout", smp2p_ut_remote_inout); - return 0; -} -late_initcall(smp2p_debugfs_init); diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 5e565c863889..7dff5d3b8d72 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -15,8 +15,7 @@ obj-$(CONFIG_MSM_GLINK_SPI_XPRT) += glink_spi_xprt.o obj-$(CONFIG_MSM_SMEM_LOGGING) += smem_log.o obj-$(CONFIG_MSM_SYSMON_GLINK_COMM) += sysmon-glink.o sysmon-qmi.o obj-$(CONFIG_ARCH_MSM8996) += kryo-l2-accessors.o -obj-$(CONFIG_MSM_SMP2P) += smp2p.o smp2p_debug.o smp2p_sleepstate.o -obj-$(CONFIG_MSM_SMP2P_TEST) += smp2p_loopback.o smp2p_test.o smp2p_spinlock_test.o +obj-$(CONFIG_MSM_SMP2P) += smp2p.o smp2p_loopback.o smp2p_debug.o smp2p_sleepstate.o obj-$(CONFIG_MSM_QMI_INTERFACE) += qmi_interface.o obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd.o obj-$(CONFIG_MSM_HVC) += hvc.o diff --git a/drivers/soc/qcom/smp2p_spinlock_test.c b/drivers/soc/qcom/smp2p_spinlock_test.c deleted file mode 100644 index 1fe4411eebde..000000000000 --- a/drivers/soc/qcom/smp2p_spinlock_test.c +++ /dev/null @@ -1,819 +0,0 @@ -/* drivers/soc/qcom/smp2p_spinlock_test.c - * - * 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 - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "smem_private.h" -#include "smp2p_private.h" -#include "smp2p_test_common.h" - -#define RS_END_THIEF_PID_BIT 20 -#define RS_END_THIEF_MASK 0x00f00000 - -/* Spinlock commands used for testing Apps<->RPM spinlocks. */ -enum RPM_SPINLOCK_CMDS { - RPM_CMD_INVALID, - RPM_CMD_START, - RPM_CMD_LOCKED, - RPM_CMD_UNLOCKED, - RPM_CMD_END, -}; - -/* Shared structure for testing Apps<->RPM spinlocks. */ -struct rpm_spinlock_test { - uint32_t apps_cmd; - uint32_t apps_lock_count; - uint32_t rpm_cmd; - uint32_t rpm_lock_count; -}; - -static uint32_t ut_remote_spinlock_run_time = 1; - -/** - * smp2p_ut_remote_spinlock_core - Verify remote spinlock. - * - * @s: Pointer to output file - * @remote_pid: Remote processor to test - * @use_trylock: Use trylock to prevent an Apps deadlock if the - * remote spinlock fails. - */ -static void smp2p_ut_remote_spinlock_core(struct seq_file *s, int remote_pid, - bool use_trylock) -{ - int failed = 0; - unsigned lock_count = 0; - struct msm_smp2p_out *handle = NULL; - int ret; - uint32_t test_request; - uint32_t test_response; - struct mock_cb_data cb_out; - struct mock_cb_data cb_in; - unsigned long flags; - unsigned n; - bool have_lock; - bool timeout; - int failed_tmp; - int spinlock_owner; - remote_spinlock_t *smem_spinlock; - unsigned long end; - - seq_printf(s, "Running %s for '%s' remote pid %d\n", - __func__, smp2p_pid_to_name(remote_pid), remote_pid); - - cb_out.initialized = false; - cb_in.initialized = false; - mock_cb_data_init(&cb_out); - mock_cb_data_init(&cb_in); - do { - smem_spinlock = smem_get_remote_spinlock(); - UT_ASSERT_PTR(smem_spinlock, !=, NULL); - - /* Open output entry */ - ret = msm_smp2p_out_open(remote_pid, SMP2P_RLPB_ENTRY_NAME, - &cb_out.nb, &handle); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_out.cb_completion, HZ * 2), - >, 0); - UT_ASSERT_INT(cb_out.cb_count, ==, 1); - UT_ASSERT_INT(cb_out.event_open, ==, 1); - - /* Open inbound entry */ - ret = msm_smp2p_in_register(remote_pid, SMP2P_RLPB_ENTRY_NAME, - &cb_in.nb); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ * 2), - >, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 1); - UT_ASSERT_INT(cb_in.event_open, ==, 1); - - /* Send start */ - mock_cb_data_reset(&cb_in); - mock_cb_data_reset(&cb_out); - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE_REQ(test_request); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_START); - SMP2P_SET_RMT_DATA(test_request, 0x0); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_INT(ret, ==, 0); - - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ * 2), - >, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 1); - UT_ASSERT_INT(cb_in.event_entry_update, ==, 1); - ret = msm_smp2p_in_read(remote_pid, SMP2P_RLPB_ENTRY_NAME, - &test_response); - UT_ASSERT_INT(ret, ==, 0); - - test_response = SMP2P_GET_RMT_CMD(test_response); - if (test_response != SMP2P_LB_CMD_RSPIN_LOCKED && - test_response != SMP2P_LB_CMD_RSPIN_UNLOCKED) { - /* invalid response from remote - abort test */ - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, 0x0); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_HEX(SMP2P_LB_CMD_RSPIN_LOCKED, ==, - test_response); - } - - /* Run spinlock test */ - if (use_trylock) - seq_puts(s, "\tUsing remote_spin_trylock\n"); - else - seq_puts(s, "\tUsing remote_spin_lock\n"); - - flags = 0; - have_lock = false; - timeout = false; - spinlock_owner = 0; - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE_REQ(test_request); - end = jiffies + (ut_remote_spinlock_run_time * HZ); - if (ut_remote_spinlock_run_time < 300) { - seq_printf(s, "\tRunning test for %u seconds; ", - ut_remote_spinlock_run_time); - seq_puts(s, - "on physical hardware please run >= 300 seconds by doing 'echo 300 > ut_remote_spinlock_time'\n"); - } - while (time_is_after_jiffies(end)) { - /* try to acquire spinlock */ - if (use_trylock) { - unsigned long j_start = jiffies; - while (!remote_spin_trylock_irqsave( - smem_spinlock, flags)) { - if (jiffies_to_msecs(jiffies - j_start) - > 1000) { - seq_puts(s, - "\tFail: Timeout trying to get the lock\n"); - timeout = true; - break; - } - } - if (timeout) - break; - } else { - remote_spin_lock_irqsave(smem_spinlock, flags); - } - have_lock = true; - ++lock_count; - - /* tell the remote side that we have the lock */ - SMP2P_SET_RMT_DATA(test_request, lock_count); - SMP2P_SET_RMT_CMD(test_request, - SMP2P_LB_CMD_RSPIN_LOCKED); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_INT(ret, ==, 0); - - /* verify the other side doesn't say it has the lock */ - for (n = 0; n < 1000; ++n) { - spinlock_owner = - remote_spin_owner(smem_spinlock); - if (spinlock_owner != SMEM_APPS) { - /* lock stolen by remote side */ - seq_puts(s, "\tFail: Remote side: "); - seq_printf(s, "%d stole lock pid: %d\n", - remote_pid, spinlock_owner); - failed = true; - break; - } - spinlock_owner = 0; - - ret = msm_smp2p_in_read(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &test_response); - UT_ASSERT_INT(ret, ==, 0); - test_response = - SMP2P_GET_RMT_CMD(test_response); - UT_ASSERT_HEX(SMP2P_LB_CMD_RSPIN_UNLOCKED, ==, - test_response); - } - if (failed) - break; - - /* tell remote side we are unlocked and release lock */ - SMP2P_SET_RMT_CMD(test_request, - SMP2P_LB_CMD_RSPIN_UNLOCKED); - (void)msm_smp2p_out_write(handle, test_request); - have_lock = false; - remote_spin_unlock_irqrestore(smem_spinlock, flags); - } - if (have_lock) - remote_spin_unlock_irqrestore(smem_spinlock, flags); - - /* End test */ - mock_cb_data_reset(&cb_in); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, lock_count | - (spinlock_owner << RS_END_THIEF_PID_BIT)); - (void)msm_smp2p_out_write(handle, test_request); - - failed_tmp = failed; - failed = false; - do { - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ * 2), - >, 0); - reinit_completion(&cb_in.cb_completion); - ret = msm_smp2p_in_read(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &test_response); - UT_ASSERT_INT(ret, ==, 0); - } while (!failed && - SMP2P_GET_RMT_CMD(test_response) != - SMP2P_LB_CMD_RSPIN_END); - if (failed) - break; - failed = failed_tmp; - - test_response = SMP2P_GET_RMT_DATA(test_response); - seq_puts(s, "\tLocked spinlock "); - seq_printf(s, "local %u times; remote %u times", - lock_count, - test_response & ((1 << RS_END_THIEF_PID_BIT) - 1) - ); - if (test_response & RS_END_THIEF_MASK) { - seq_puts(s, "Remote side reporting lock stolen by "); - seq_printf(s, "pid %d.\n", - SMP2P_GET_BITS(test_response, - RS_END_THIEF_MASK, - RS_END_THIEF_PID_BIT)); - failed = 1; - } - seq_puts(s, "\n"); - - /* Cleanup */ - ret = msm_smp2p_out_close(&handle); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_PTR(handle, ==, NULL); - ret = msm_smp2p_in_unregister(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &cb_in.nb); - UT_ASSERT_INT(ret, ==, 0); - - if (!failed && !timeout) - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - if (handle) { - /* send end command */ - test_request = 0; - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, lock_count); - (void)msm_smp2p_out_write(handle, test_request); - (void)msm_smp2p_out_close(&handle); - } - (void)msm_smp2p_in_unregister(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &cb_in.nb); - - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -/** - * smp2p_ut_remote_spinlock_pid - Verify remote spinlock for a processor. - * - * @s: Pointer to output file - * @pid: Processor to test - * @use_trylock: Use trylock to prevent an Apps deadlock if the - * remote spinlock fails. - */ -static void smp2p_ut_remote_spinlock_pid(struct seq_file *s, int pid, - bool use_trylock) -{ - struct smp2p_interrupt_config *int_cfg; - - int_cfg = smp2p_get_interrupt_config(); - if (!int_cfg) { - seq_puts(s, "Remote processor config unavailable\n"); - return; - } - - if (pid >= SMP2P_NUM_PROCS || !int_cfg[pid].is_configured) - return; - - msm_smp2p_deinit_rmt_lpb_proc(pid); - smp2p_ut_remote_spinlock_core(s, pid, use_trylock); - msm_smp2p_init_rmt_lpb_proc(pid); -} - -/** - * smp2p_ut_remote_spinlock - Verify remote spinlock for all processors. - * - * @s: pointer to output file - */ -static void smp2p_ut_remote_spinlock(struct seq_file *s) -{ - int pid; - - for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) - smp2p_ut_remote_spinlock_pid(s, pid, false); -} - -/** - * smp2p_ut_remote_spin_trylock - Verify remote trylock for all processors. - * - * @s: Pointer to output file - */ -static void smp2p_ut_remote_spin_trylock(struct seq_file *s) -{ - int pid; - - for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) - smp2p_ut_remote_spinlock_pid(s, pid, true); -} - -/** - * smp2p_ut_remote_spinlock - Verify remote spinlock for all processors. - * - * @s: pointer to output file - * - * This test verifies inbound and outbound functionality for all - * configured remote processor. - */ -static void smp2p_ut_remote_spinlock_modem(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_MODEM_PROC, false); -} - -static void smp2p_ut_remote_spinlock_adsp(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_AUDIO_PROC, false); -} - -static void smp2p_ut_remote_spinlock_dsps(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_SENSOR_PROC, false); -} - -static void smp2p_ut_remote_spinlock_wcnss(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_WIRELESS_PROC, false); -} - -static void smp2p_ut_remote_spinlock_cdsp(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_CDSP_PROC, false); -} - -static void smp2p_ut_remote_spinlock_tz(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_TZ_PROC, false); -} - -/** - * smp2p_ut_remote_spinlock_rpm - Verify remote spinlock. - * - * @s: pointer to output file - * @remote_pid: Remote processor to test - */ -static void smp2p_ut_remote_spinlock_rpm(struct seq_file *s) -{ - int failed = 0; - unsigned long flags; - unsigned n; - unsigned test_num; - struct rpm_spinlock_test *data_ptr; - remote_spinlock_t *smem_spinlock; - bool have_lock; - - seq_printf(s, "Running %s for Apps<->RPM Test\n", - __func__); - do { - smem_spinlock = smem_get_remote_spinlock(); - UT_ASSERT_PTR(smem_spinlock, !=, NULL); - - data_ptr = smem_alloc(SMEM_ID_VENDOR0, - sizeof(struct rpm_spinlock_test), 0, - SMEM_ANY_HOST_FLAG); - UT_ASSERT_PTR(0, !=, data_ptr); - - /* Send start */ - writel_relaxed(0, &data_ptr->apps_lock_count); - writel_relaxed(RPM_CMD_START, &data_ptr->apps_cmd); - - seq_puts(s, "\tWaiting for RPM to start test\n"); - for (n = 0; n < 1000; ++n) { - if (readl_relaxed(&data_ptr->rpm_cmd) != - RPM_CMD_INVALID) - break; - usleep_range(1000, 1200); - } - if (readl_relaxed(&data_ptr->rpm_cmd) == RPM_CMD_INVALID) { - /* timeout waiting for RPM */ - writel_relaxed(RPM_CMD_INVALID, &data_ptr->apps_cmd); - UT_ASSERT_INT(RPM_CMD_LOCKED, !=, RPM_CMD_INVALID); - } - - /* Run spinlock test */ - flags = 0; - have_lock = false; - for (test_num = 0; !failed && test_num < 10000; ++test_num) { - /* acquire spinlock */ - remote_spin_lock_irqsave(smem_spinlock, flags); - have_lock = true; - data_ptr->apps_lock_count++; - writel_relaxed(data_ptr->apps_lock_count, - &data_ptr->apps_lock_count); - writel_relaxed(RPM_CMD_LOCKED, &data_ptr->apps_cmd); - /* - * Ensure that the remote side sees our lock has - * been acquired before we start polling their status. - */ - wmb(); - - /* verify the other side doesn't say it has the lock */ - for (n = 0; n < 1000; ++n) { - UT_ASSERT_HEX(RPM_CMD_UNLOCKED, ==, - readl_relaxed(&data_ptr->rpm_cmd)); - } - if (failed) - break; - - /* release spinlock */ - have_lock = false; - writel_relaxed(RPM_CMD_UNLOCKED, &data_ptr->apps_cmd); - /* - * Ensure that our status-update write was committed - * before we unlock the spinlock. - */ - wmb(); - remote_spin_unlock_irqrestore(smem_spinlock, flags); - } - if (have_lock) - remote_spin_unlock_irqrestore(smem_spinlock, flags); - - /* End test */ - writel_relaxed(RPM_CMD_INVALID, &data_ptr->apps_cmd); - seq_printf(s, "\tLocked spinlock local %u remote %u\n", - readl_relaxed(&data_ptr->apps_lock_count), - readl_relaxed(&data_ptr->rpm_lock_count)); - - if (!failed) - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -struct rmt_spinlock_work_item { - struct work_struct work; - struct completion try_lock; - struct completion locked; - bool has_locked; -}; - -static void ut_remote_spinlock_ssr_worker(struct work_struct *work) -{ - remote_spinlock_t *smem_spinlock; - unsigned long flags; - struct rmt_spinlock_work_item *work_item = - container_of(work, struct rmt_spinlock_work_item, work); - - work_item->has_locked = false; - complete(&work_item->try_lock); - smem_spinlock = smem_get_remote_spinlock(); - if (!smem_spinlock) { - pr_err("%s Failed\n", __func__); - return; - } - - remote_spin_lock_irqsave(smem_spinlock, flags); - remote_spin_unlock_irqrestore(smem_spinlock, flags); - work_item->has_locked = true; - complete(&work_item->locked); -} - -/** - * smp2p_ut_remote_spinlock_ssr - Verify remote spinlock. - * - * @s: pointer to output file - */ -static void smp2p_ut_remote_spinlock_ssr(struct seq_file *s) -{ - int failed = 0; - unsigned long flags; - remote_spinlock_t *smem_spinlock; - int spinlock_owner = 0; - - struct workqueue_struct *ws = NULL; - struct rmt_spinlock_work_item work_item = { .has_locked = false }; - - seq_printf(s, " Running %s Test\n", - __func__); - do { - smem_spinlock = smem_get_remote_spinlock(); - UT_ASSERT_PTR(smem_spinlock, !=, NULL); - - ws = create_singlethread_workqueue("ut_remote_spinlock_ssr"); - UT_ASSERT_PTR(ws, !=, NULL); - INIT_WORK(&work_item.work, ut_remote_spinlock_ssr_worker); - init_completion(&work_item.try_lock); - init_completion(&work_item.locked); - - remote_spin_lock_irqsave(smem_spinlock, flags); - /* Unlock local spin lock and hold HW spinlock */ - spin_unlock_irqrestore(&((smem_spinlock)->local), flags); - - queue_work(ws, &work_item.work); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &work_item.try_lock, HZ * 2), >, 0); - UT_ASSERT_INT((int)work_item.has_locked, ==, 0); - spinlock_owner = remote_spin_owner(smem_spinlock); - UT_ASSERT_INT(spinlock_owner, ==, SMEM_APPS); - remote_spin_release_all(SMEM_APPS); - - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &work_item.locked, HZ * 2), >, 0); - - if (!failed) - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -/** - * smp2p_ut_remote_spinlock_track_core - Verify remote spinlock. - * - * @s: Pointer to output file - * @remote_pid: Remote processor to test - * - * This test has the remote subsystem grab the lock, and then has the local - * subsystem attempt to grab the lock using the trylock() API. It then verifies - * that the ID in the hw_spinlocks array matches the owner of the lock. - */ -static void smp2p_ut_remote_spinlock_track_core(struct seq_file *s, - int remote_pid) -{ - int failed = 0; - struct msm_smp2p_out *handle = NULL; - int ret; - uint32_t test_request; - uint32_t test_response; - struct mock_cb_data cb_out; - struct mock_cb_data cb_in; - unsigned long flags; - int stored_value; - remote_spinlock_t *smem_spinlock; - - seq_printf(s, "Running %s for '%s' remote pid %d\n", - __func__, smp2p_pid_to_name(remote_pid), remote_pid); - - cb_out.initialized = false; - cb_in.initialized = false; - mock_cb_data_init(&cb_out); - mock_cb_data_init(&cb_in); - do { - smem_spinlock = smem_get_remote_spinlock(); - UT_ASSERT_PTR(smem_spinlock, !=, NULL); - - /* Open output entry */ - ret = msm_smp2p_out_open(remote_pid, SMP2P_RLPB_ENTRY_NAME, - &cb_out.nb, &handle); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_out.cb_completion, HZ * 2), - >, 0); - UT_ASSERT_INT(cb_out.cb_count, ==, 1); - UT_ASSERT_INT(cb_out.event_open, ==, 1); - - /* Open inbound entry */ - ret = msm_smp2p_in_register(remote_pid, SMP2P_RLPB_ENTRY_NAME, - &cb_in.nb); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ * 2), - >, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 1); - UT_ASSERT_INT(cb_in.event_open, ==, 1); - - /* Send start */ - mock_cb_data_reset(&cb_in); - mock_cb_data_reset(&cb_out); - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE_REQ(test_request); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_START); - SMP2P_SET_RMT_DATA(test_request, 0x0); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_INT(ret, ==, 0); - - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ * 2), - >, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 1); - UT_ASSERT_INT(cb_in.event_entry_update, ==, 1); - ret = msm_smp2p_in_read(remote_pid, SMP2P_RLPB_ENTRY_NAME, - &test_response); - UT_ASSERT_INT(ret, ==, 0); - - test_response = SMP2P_GET_RMT_CMD(test_response); - if (test_response != SMP2P_LB_CMD_RSPIN_LOCKED && - test_response != SMP2P_LB_CMD_RSPIN_UNLOCKED) { - /* invalid response from remote - abort test */ - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, 0x0); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_HEX(SMP2P_LB_CMD_RSPIN_LOCKED, ==, - test_response); - } - - /* Run spinlock test */ - flags = 0; - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE_REQ(test_request); - - /* try to acquire spinlock */ - remote_spin_trylock_irqsave(smem_spinlock, flags); - /* - * Need to check against the locking token (PID + 1) - * because the remote_spin_owner() API only returns the - * PID. - */ - stored_value = remote_spin_get_hw_spinlocks_element( - smem_spinlock); - UT_ASSERT_INT(stored_value, ==, - remote_spin_owner(smem_spinlock) + 1); - UT_ASSERT_INT(stored_value, ==, remote_pid + 1); - - /* End test */ - test_request = 0x0; - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, 0x0); - (void)msm_smp2p_out_write(handle, test_request); - - /* Cleanup */ - ret = msm_smp2p_out_close(&handle); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_PTR(handle, ==, NULL); - ret = msm_smp2p_in_unregister(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &cb_in.nb); - UT_ASSERT_INT(ret, ==, 0); - - if (!failed) - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - if (handle) { - /* send end command */ - test_request = 0x0; - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, 0x0); - (void)msm_smp2p_out_write(handle, test_request); - (void)msm_smp2p_out_close(&handle); - } - (void)msm_smp2p_in_unregister(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &cb_in.nb); - - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -/** - * smp2p_ut_remote_spinlock_track - Verify PID tracking for modem. - * - * @s: Pointer to output file - * @pid: The processor to test - */ -static void smp2p_ut_remote_spinlock_track(struct seq_file *s, int pid) -{ - struct smp2p_interrupt_config *int_cfg; - - int_cfg = smp2p_get_interrupt_config(); - if (!int_cfg) { - seq_puts(s, "Remote processor config unavailable\n"); - return; - } - - if (pid >= SMP2P_NUM_PROCS || !int_cfg[pid].is_configured) - return; - - msm_smp2p_deinit_rmt_lpb_proc(pid); - smp2p_ut_remote_spinlock_track_core(s, pid); - msm_smp2p_init_rmt_lpb_proc(pid); -} - -/** - * smp2p_ut_remote_spinlock_track - Verify PID tracking for all processors. - * - * @s: Pointer to output file - * - * This test verifies PID tracking for all configured remote processors. - */ -static void smp2p_ut_remote_spinlock_track_modem(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_MODEM_PROC); -} - -static void smp2p_ut_remote_spinlock_track_adsp(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_AUDIO_PROC); -} - -static void smp2p_ut_remote_spinlock_track_dsps(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_SENSOR_PROC); -} - -static void smp2p_ut_remote_spinlock_track_wcnss(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_WIRELESS_PROC); -} - -static void smp2p_ut_remote_spinlock_track_cdsp(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_CDSP_PROC); -} - -static void smp2p_ut_remote_spinlock_track_tz(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_TZ_PROC); -} - -static int __init smp2p_debugfs_init(void) -{ - /* - * Add Unit Test entries. - * - * The idea with unit tests is that you can run all of them - * from ADB shell by doing: - * adb shell - * cat ut* - * - * And if particular tests fail, you can then repeatedly run the - * failing tests as you debug and resolve the failing test. - */ - smp2p_debug_create("ut_remote_spinlock", - smp2p_ut_remote_spinlock); - smp2p_debug_create("ut_remote_spin_trylock", - smp2p_ut_remote_spin_trylock); - smp2p_debug_create("ut_remote_spinlock_modem", - smp2p_ut_remote_spinlock_modem); - smp2p_debug_create("ut_remote_spinlock_adsp", - smp2p_ut_remote_spinlock_adsp); - smp2p_debug_create("ut_remote_spinlock_dsps", - smp2p_ut_remote_spinlock_dsps); - smp2p_debug_create("ut_remote_spinlock_wcnss", - smp2p_ut_remote_spinlock_wcnss); - smp2p_debug_create("ut_remote_spinlock_cdsp", - smp2p_ut_remote_spinlock_cdsp); - smp2p_debug_create("ut_remote_spinlock_tz", - smp2p_ut_remote_spinlock_tz); - smp2p_debug_create("ut_remote_spinlock_rpm", - smp2p_ut_remote_spinlock_rpm); - smp2p_debug_create_u32("ut_remote_spinlock_time", - &ut_remote_spinlock_run_time); - smp2p_debug_create("ut_remote_spinlock_ssr", - &smp2p_ut_remote_spinlock_ssr); - smp2p_debug_create("ut_remote_spinlock_track_modem", - &smp2p_ut_remote_spinlock_track_modem); - smp2p_debug_create("ut_remote_spinlock_track_adsp", - &smp2p_ut_remote_spinlock_track_adsp); - smp2p_debug_create("ut_remote_spinlock_track_dsps", - &smp2p_ut_remote_spinlock_track_dsps); - smp2p_debug_create("ut_remote_spinlock_track_wcnss", - &smp2p_ut_remote_spinlock_track_wcnss); - smp2p_debug_create("ut_remote_spinlock_track_cdsp", - &smp2p_ut_remote_spinlock_track_cdsp); - smp2p_debug_create("ut_remote_spinlock_track_tz", - &smp2p_ut_remote_spinlock_track_tz); - return 0; -} -module_init(smp2p_debugfs_init); diff --git a/drivers/soc/qcom/smp2p_test.c b/drivers/soc/qcom/smp2p_test.c deleted file mode 100644 index e81bada0137a..000000000000 --- a/drivers/soc/qcom/smp2p_test.c +++ /dev/null @@ -1,1327 +0,0 @@ -/* drivers/soc/qcom/smp2p_test.c - * - * 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 - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "smp2p_private.h" -#include "smp2p_test_common.h" - -/** - * smp2p_ut_local_basic - Basic sanity test using local loopback. - * - * @s: pointer to output file - * - * This test simulates a simple write and read - * when remote processor does not exist. - */ -static void smp2p_ut_local_basic(struct seq_file *s) -{ - int failed = 0; - struct msm_smp2p_out *smp2p_obj; - struct msm_smp2p_remote_mock *rmp = NULL; - int ret; - uint32_t test_request; - uint32_t test_response = 0; - static struct mock_cb_data cb_data; - - seq_printf(s, "Running %s\n", __func__); - mock_cb_data_init(&cb_data); - do { - /* initialize mock edge and start opening */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - rmp = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(rmp, !=, NULL); - - rmp->rx_interrupt_count = 0; - memset(&rmp->remote_item, 0, - sizeof(struct smp2p_smem_item)); - - msm_smp2p_set_remote_mock_exists(false); - - ret = msm_smp2p_out_open(SMP2P_REMOTE_MOCK_PROC, "smp2p", - &cb_data.nb, &smp2p_obj); - UT_ASSERT_INT(ret, ==, 0); - - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - UT_ASSERT_INT(cb_data.cb_count, ==, 0); - rmp->rx_interrupt_count = 0; - - /* simulate response from remote side */ - rmp->remote_item.header.magic = SMP2P_MAGIC; - SMP2P_SET_LOCAL_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_REMOTE_MOCK_PROC); - SMP2P_SET_REMOTE_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_APPS_PROC); - SMP2P_SET_VERSION( - rmp->remote_item.header.feature_version, 1); - SMP2P_SET_FEATURES( - rmp->remote_item.header.feature_version, 0); - SMP2P_SET_ENT_TOTAL( - rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY); - SMP2P_SET_ENT_VALID( - rmp->remote_item.header.valid_total_ent, 0); - rmp->remote_item.header.flags = 0x0; - msm_smp2p_set_remote_mock_exists(true); - rmp->tx_interrupt(); - - /* verify port was opened */ - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_data.cb_completion, HZ / 2), >, 0); - UT_ASSERT_INT(cb_data.cb_count, ==, 1); - UT_ASSERT_INT(cb_data.event_open, ==, 1); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 2); - - /* do write (test outbound entries) */ - rmp->rx_interrupt_count = 0; - test_request = 0xC0DE; - ret = msm_smp2p_out_write(smp2p_obj, test_request); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - - /* do read (test inbound entries) */ - ret = msm_smp2p_out_read(smp2p_obj, &test_response); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(test_request, ==, test_response); - - ret = msm_smp2p_out_close(&smp2p_obj); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_PTR(smp2p_obj, ==, 0); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - (void)msm_smp2p_out_close(&smp2p_obj); - } -} - -/** - * smp2p_ut_local_late_open - Verify post-negotiation opening. - * - * @s: pointer to output file - * - * Verify entry creation for opening entries after negotiation is complete. - */ -static void smp2p_ut_local_late_open(struct seq_file *s) -{ - int failed = 0; - struct msm_smp2p_out *smp2p_obj; - struct msm_smp2p_remote_mock *rmp = NULL; - int ret; - uint32_t test_request; - uint32_t test_response = 0; - static struct mock_cb_data cb_data; - - seq_printf(s, "Running %s\n", __func__); - mock_cb_data_init(&cb_data); - do { - /* initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - rmp = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(rmp, !=, NULL); - - rmp->rx_interrupt_count = 0; - memset(&rmp->remote_item, 0, - sizeof(struct smp2p_smem_item)); - rmp->remote_item.header.magic = SMP2P_MAGIC; - SMP2P_SET_LOCAL_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_REMOTE_MOCK_PROC); - SMP2P_SET_REMOTE_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_APPS_PROC); - SMP2P_SET_VERSION( - rmp->remote_item.header.feature_version, 1); - SMP2P_SET_FEATURES( - rmp->remote_item.header.feature_version, 0); - SMP2P_SET_ENT_TOTAL( - rmp->remote_item.header.valid_total_ent, - SMP2P_MAX_ENTRY); - SMP2P_SET_ENT_VALID( - rmp->remote_item.header.valid_total_ent, 0); - rmp->remote_item.header.flags = 0x0; - - msm_smp2p_set_remote_mock_exists(true); - - ret = msm_smp2p_out_open(SMP2P_REMOTE_MOCK_PROC, "smp2p", - &cb_data.nb, &smp2p_obj); - UT_ASSERT_INT(ret, ==, 0); - - /* verify port was opened */ - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_data.cb_completion, HZ / 2), - >, 0); - UT_ASSERT_INT(cb_data.cb_count, ==, 1); - UT_ASSERT_INT(cb_data.event_open, ==, 1); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 2); - - /* do write (test outbound entries) */ - rmp->rx_interrupt_count = 0; - test_request = 0xC0DE; - ret = msm_smp2p_out_write(smp2p_obj, test_request); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - - /* do read (test inbound entries) */ - ret = msm_smp2p_out_read(smp2p_obj, &test_response); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(test_request, ==, test_response); - - ret = msm_smp2p_out_close(&smp2p_obj); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_PTR(smp2p_obj, ==, 0); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - (void)msm_smp2p_out_close(&smp2p_obj); - } -} - -/** - * smp2p_ut_local_early_open - Verify pre-negotiation opening. - * - * @s: pointer to output file - * - * Verify entry creation for opening entries before negotiation is complete. - */ -static void smp2p_ut_local_early_open(struct seq_file *s) -{ - int failed = 0; - struct msm_smp2p_out *smp2p_obj; - struct msm_smp2p_remote_mock *rmp = NULL; - struct smp2p_smem *outbound_item; - int negotiation_state; - int ret; - uint32_t test_request; - uint32_t test_response = 0; - static struct mock_cb_data cb_data; - - seq_printf(s, "Running %s\n", __func__); - mock_cb_data_init(&cb_data); - do { - /* initialize mock edge, but don't enable, yet */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - rmp = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(rmp, !=, NULL); - - rmp->rx_interrupt_count = 0; - memset(&rmp->remote_item, 0, - sizeof(struct smp2p_smem_item)); - rmp->remote_item.header.magic = SMP2P_MAGIC; - SMP2P_SET_LOCAL_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_REMOTE_MOCK_PROC); - SMP2P_SET_REMOTE_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_APPS_PROC); - SMP2P_SET_VERSION( - rmp->remote_item.header.feature_version, 1); - SMP2P_SET_FEATURES( - rmp->remote_item.header.feature_version, 0); - SMP2P_SET_ENT_TOTAL( - rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY); - SMP2P_SET_ENT_VALID( - rmp->remote_item.header.valid_total_ent, 0); - rmp->remote_item.header.flags = 0x0; - - msm_smp2p_set_remote_mock_exists(false); - UT_ASSERT_PTR(NULL, ==, - smp2p_get_in_item(SMP2P_REMOTE_MOCK_PROC)); - - /* initiate open, but verify it doesn't complete */ - ret = msm_smp2p_out_open(SMP2P_REMOTE_MOCK_PROC, "smp2p", - &cb_data.nb, &smp2p_obj); - UT_ASSERT_INT(ret, ==, 0); - - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_data.cb_completion, HZ / 8), - ==, 0); - UT_ASSERT_INT(cb_data.cb_count, ==, 0); - UT_ASSERT_INT(cb_data.event_open, ==, 0); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - - outbound_item = smp2p_get_out_item(SMP2P_REMOTE_MOCK_PROC, - &negotiation_state); - UT_ASSERT_PTR(outbound_item, !=, NULL); - UT_ASSERT_INT(negotiation_state, ==, SMP2P_EDGE_STATE_OPENING); - UT_ASSERT_INT(0, ==, - SMP2P_GET_ENT_VALID(outbound_item->valid_total_ent)); - - /* verify that read/write don't work yet */ - rmp->rx_interrupt_count = 0; - test_request = 0x0; - ret = msm_smp2p_out_write(smp2p_obj, test_request); - UT_ASSERT_INT(ret, ==, -ENODEV); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 0); - - ret = msm_smp2p_out_read(smp2p_obj, &test_response); - UT_ASSERT_INT(ret, ==, -ENODEV); - - /* allocate remote entry and verify open */ - msm_smp2p_set_remote_mock_exists(true); - rmp->tx_interrupt(); - - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_data.cb_completion, HZ / 2), - >, 0); - UT_ASSERT_INT(cb_data.cb_count, ==, 1); - UT_ASSERT_INT(cb_data.event_open, ==, 1); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 2); - - /* do write (test outbound entries) */ - rmp->rx_interrupt_count = 0; - test_request = 0xC0DE; - ret = msm_smp2p_out_write(smp2p_obj, test_request); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - - /* do read (test inbound entries) */ - ret = msm_smp2p_out_read(smp2p_obj, &test_response); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(test_request, ==, test_response); - - ret = msm_smp2p_out_close(&smp2p_obj); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_PTR(smp2p_obj, ==, 0); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - (void)msm_smp2p_out_close(&smp2p_obj); - } -} - -/** - * smp2p_ut_mock_loopback - Exercise the remote loopback using remote mock. - * - * @s: pointer to output file - * - * This test exercises the remote loopback code using - * remote mock object. The remote mock object simulates the remote - * processor sending remote loopback commands to the local processor. - */ -static void smp2p_ut_mock_loopback(struct seq_file *s) -{ - int failed = 0; - struct msm_smp2p_remote_mock *rmp = NULL; - int ret; - uint32_t test_request = 0; - uint32_t test_response = 0; - struct msm_smp2p_out *local; - - seq_printf(s, "Running %s\n", __func__); - do { - /* Initialize the mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - rmp = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(rmp, !=, NULL); - - memset(&rmp->remote_item, 0, - sizeof(struct smp2p_smem_item)); - rmp->remote_item.header.magic = SMP2P_MAGIC; - SMP2P_SET_LOCAL_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_REMOTE_MOCK_PROC); - SMP2P_SET_REMOTE_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_APPS_PROC); - SMP2P_SET_VERSION( - rmp->remote_item.header.feature_version, 1); - SMP2P_SET_FEATURES( - rmp->remote_item.header.feature_version, 0); - SMP2P_SET_ENT_TOTAL( - rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY); - SMP2P_SET_ENT_VALID( - rmp->remote_item.header.valid_total_ent, 1); - rmp->remote_item.header.flags = 0x0; - msm_smp2p_set_remote_mock_exists(true); - - /* Create test entry and attach loopback server */ - rmp->rx_interrupt_count = 0; - reinit_completion(&rmp->cb_completion); - strlcpy(rmp->remote_item.entries[0].name, "smp2p", - SMP2P_MAX_ENTRY_NAME); - rmp->remote_item.entries[0].entry = 0; - rmp->tx_interrupt(); - - local = msm_smp2p_init_rmt_lpb_proc(SMP2P_REMOTE_MOCK_PROC); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &rmp->cb_completion, HZ / 2), - >, 0); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 2); - - /* Send Echo Command */ - rmp->rx_interrupt_count = 0; - reinit_completion(&rmp->cb_completion); - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_ECHO); - SMP2P_SET_RMT_DATA(test_request, 10); - rmp->remote_item.entries[0].entry = test_request; - rmp->tx_interrupt(); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &rmp->cb_completion, HZ / 2), - >, 0); - - /* Verify Echo Response */ - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - ret = msm_smp2p_out_read(local, - &test_response); - UT_ASSERT_INT(ret, ==, 0); - test_response = SMP2P_GET_RMT_DATA(test_response); - UT_ASSERT_INT(test_response, ==, 10); - - /* Send PINGPONG command */ - test_request = 0; - test_response = 0; - rmp->rx_interrupt_count = 0; - reinit_completion(&rmp->cb_completion); - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_PINGPONG); - SMP2P_SET_RMT_DATA(test_request, 10); - rmp->remote_item.entries[0].entry = test_request; - rmp->tx_interrupt(); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &rmp->cb_completion, HZ / 2), - >, 0); - - /* Verify PINGPONG Response */ - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - ret = msm_smp2p_out_read(local, &test_response); - UT_ASSERT_INT(ret, ==, 0); - test_response = SMP2P_GET_RMT_DATA(test_response); - UT_ASSERT_INT(test_response, ==, 9); - - /* Send CLEARALL command */ - test_request = 0; - test_response = 0; - rmp->rx_interrupt_count = 0; - reinit_completion(&rmp->cb_completion); - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_CLEARALL); - SMP2P_SET_RMT_DATA(test_request, 10); - rmp->remote_item.entries[0].entry = test_request; - rmp->tx_interrupt(); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &rmp->cb_completion, HZ / 2), - >, 0); - - /* Verify CLEARALL response */ - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - ret = msm_smp2p_out_read(local, &test_response); - UT_ASSERT_INT(ret, ==, 0); - test_response = SMP2P_GET_RMT_DATA(test_response); - UT_ASSERT_INT(test_response, ==, 0); - - ret = msm_smp2p_deinit_rmt_lpb_proc(SMP2P_REMOTE_MOCK_PROC); - UT_ASSERT_INT(ret, ==, 0); - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - msm_smp2p_deinit_rmt_lpb_proc(SMP2P_REMOTE_MOCK_PROC); - } -} - -/** - * smp2p_ut_remote_inout_core - Verify inbound/outbound functionality. - * - * @s: pointer to output file - * @remote_pid: Remote processor to test - * - * This test verifies inbound/outbound functionality for the remote processor. - */ -static void smp2p_ut_remote_inout_core(struct seq_file *s, int remote_pid) -{ - int failed = 0; - struct msm_smp2p_out *handle; - int ret; - uint32_t test_request; - uint32_t test_response = 0; - static struct mock_cb_data cb_out; - static struct mock_cb_data cb_in; - - seq_printf(s, "Running %s for '%s' remote pid %d\n", - __func__, smp2p_pid_to_name(remote_pid), remote_pid); - mock_cb_data_init(&cb_out); - mock_cb_data_init(&cb_in); - do { - /* Open output entry */ - ret = msm_smp2p_out_open(remote_pid, "smp2p", - &cb_out.nb, &handle); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_out.cb_completion, HZ / 2), - >, 0); - UT_ASSERT_INT(cb_out.cb_count, ==, 1); - UT_ASSERT_INT(cb_out.event_open, ==, 1); - - /* Open inbound entry */ - ret = msm_smp2p_in_register(remote_pid, "smp2p", - &cb_in.nb); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ / 2), - >, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 1); - UT_ASSERT_INT(cb_in.event_open, ==, 1); - - /* Write an echo request */ - mock_cb_data_reset(&cb_out); - mock_cb_data_reset(&cb_in); - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_ECHO); - SMP2P_SET_RMT_DATA(test_request, 0xAA55); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_INT(ret, ==, 0); - - /* Verify inbound reply */ - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ / 2), - >, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 1); - UT_ASSERT_INT(cb_in.event_entry_update, ==, 1); - UT_ASSERT_INT(SMP2P_GET_RMT_DATA( - cb_in.entry_data.current_value), ==, 0xAA55); - - ret = msm_smp2p_in_read(remote_pid, "smp2p", &test_response); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(0, ==, SMP2P_GET_RMT_CMD_TYPE(test_response)); - UT_ASSERT_INT(SMP2P_LB_CMD_ECHO, ==, - SMP2P_GET_RMT_CMD(test_response)); - UT_ASSERT_INT(0xAA55, ==, SMP2P_GET_RMT_DATA(test_response)); - - /* Write a clear all request */ - mock_cb_data_reset(&cb_in); - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_CLEARALL); - SMP2P_SET_RMT_DATA(test_request, 0xAA55); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_INT(ret, ==, 0); - - /* Verify inbound reply */ - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ / 2), - >, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 1); - UT_ASSERT_INT(cb_in.event_entry_update, ==, 1); - UT_ASSERT_INT(SMP2P_GET_RMT_DATA( - cb_in.entry_data.current_value), ==, 0x0000); - - ret = msm_smp2p_in_read(remote_pid, "smp2p", &test_response); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(0, ==, SMP2P_GET_RMT_CMD_TYPE(test_response)); - UT_ASSERT_INT(0x0000, ==, SMP2P_GET_RMT_DATA(test_response)); - - /* Write a decrement request */ - mock_cb_data_reset(&cb_in); - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_PINGPONG); - SMP2P_SET_RMT_DATA(test_request, 0xAA55); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_INT(ret, ==, 0); - - /* Verify inbound reply */ - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ / 2), - >, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 1); - UT_ASSERT_INT(cb_in.event_entry_update, ==, 1); - UT_ASSERT_INT(SMP2P_GET_RMT_DATA( - cb_in.entry_data.current_value), ==, 0xAA54); - - ret = msm_smp2p_in_read(remote_pid, "smp2p", &test_response); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(0, ==, SMP2P_GET_RMT_CMD_TYPE(test_response)); - UT_ASSERT_INT(SMP2P_LB_CMD_PINGPONG, ==, - SMP2P_GET_RMT_CMD(test_response)); - UT_ASSERT_INT(0xAA54, ==, SMP2P_GET_RMT_DATA(test_response)); - - /* Test the ignore flag */ - mock_cb_data_reset(&cb_in); - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_RLPB_IGNORE); - SMP2P_SET_RMT_DATA(test_request, 0xAA55); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_INT(ret, ==, 0); - - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ / 2), - ==, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 0); - UT_ASSERT_INT(cb_in.event_entry_update, ==, 0); - ret = msm_smp2p_in_read(remote_pid, "smp2p", &test_response); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(0xAA54, ==, SMP2P_GET_RMT_DATA(test_response)); - - /* Cleanup */ - ret = msm_smp2p_out_close(&handle); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_PTR(handle, ==, 0); - ret = msm_smp2p_in_unregister(remote_pid, "smp2p", &cb_in.nb); - UT_ASSERT_INT(ret, ==, 0); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - if (handle) - (void)msm_smp2p_out_close(&handle); - (void)msm_smp2p_in_unregister(remote_pid, "smp2p", &cb_in.nb); - - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -/** - * smp2p_ut_remote_inout - Verify inbound/outbound functionality for all. - * - * @s: pointer to output file - * - * This test verifies inbound and outbound functionality for all - * configured remote processor. - */ -static void smp2p_ut_remote_inout(struct seq_file *s) -{ - struct smp2p_interrupt_config *int_cfg; - int pid; - - int_cfg = smp2p_get_interrupt_config(); - if (!int_cfg) { - seq_puts(s, "Remote processor config unavailable\n"); - return; - } - - for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) { - if (!int_cfg[pid].is_configured) - continue; - - msm_smp2p_deinit_rmt_lpb_proc(pid); - smp2p_ut_remote_inout_core(s, pid); - msm_smp2p_init_rmt_lpb_proc(pid); - } -} - -/** - * smp2p_ut_remote_out_max_entries_core - Verify open functionality. - * - * @s: pointer to output file - * @remote_pid: Remote processor for which the test is executed. - * - * This test verifies open functionality by creating maximum outbound entries. - */ -static void smp2p_ut_remote_out_max_entries_core(struct seq_file *s, - int remote_pid) -{ - int j = 0; - int failed = 0; - struct msm_smp2p_out *handle[SMP2P_MAX_ENTRY]; - int ret; - static struct mock_cb_data cb_out[SMP2P_MAX_ENTRY]; - char entry_name[SMP2P_MAX_ENTRY_NAME]; - int num_created; - - seq_printf(s, "Running %s for '%s' remote pid %d\n", - __func__, smp2p_pid_to_name(remote_pid), remote_pid); - - for (j = 0; j < SMP2P_MAX_ENTRY; j++) { - handle[j] = NULL; - mock_cb_data_init(&cb_out[j]); - } - - do { - num_created = 0; - for (j = 0; j < SMP2P_MAX_ENTRY; j++) { - /* Open as many output entries as possible */ - scnprintf((char *)entry_name, SMP2P_MAX_ENTRY_NAME, - "smp2p%d", j); - ret = msm_smp2p_out_open(remote_pid, entry_name, - &cb_out[j].nb, &handle[j]); - if (ret == -ENOMEM) - /* hit max number */ - break; - UT_ASSERT_INT(ret, ==, 0); - ++num_created; - } - if (failed) - break; - - /* verify we created more than 1 entry */ - UT_ASSERT_INT(num_created, <=, SMP2P_MAX_ENTRY); - UT_ASSERT_INT(num_created, >, 0); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } - - /* cleanup */ - for (j = 0; j < SMP2P_MAX_ENTRY; j++) - ret = msm_smp2p_out_close(&handle[j]); -} - -/** - * smp2p_ut_remote_out_max_entries - Verify open for all configured processors. - * - * @s: pointer to output file - * - * This test verifies creating max number of entries for - * all configured remote processor. - */ -static void smp2p_ut_remote_out_max_entries(struct seq_file *s) -{ - struct smp2p_interrupt_config *int_cfg; - int pid; - - int_cfg = smp2p_get_interrupt_config(); - if (!int_cfg) { - seq_puts(s, "Remote processor config unavailable\n"); - return; - } - - for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) { - if (!int_cfg[pid].is_configured) - continue; - - smp2p_ut_remote_out_max_entries_core(s, pid); - } -} - -/** - * smp2p_ut_local_in_max_entries - Verify registering and unregistering. - * - * @s: pointer to output file - * - * This test verifies registering and unregistering for inbound entries using - * the remote mock processor. - */ -static void smp2p_ut_local_in_max_entries(struct seq_file *s) -{ - int j = 0; - int failed = 0; - struct msm_smp2p_remote_mock *rmp = NULL; - int ret; - static struct mock_cb_data cb_in[SMP2P_MAX_ENTRY]; - static struct mock_cb_data cb_out; - - seq_printf(s, "Running %s\n", __func__); - - for (j = 0; j < SMP2P_MAX_ENTRY; j++) - mock_cb_data_init(&cb_in[j]); - - mock_cb_data_init(&cb_out); - - do { - /* Initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - rmp = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(rmp, !=, NULL); - - rmp->rx_interrupt_count = 0; - memset(&rmp->remote_item, 0, - sizeof(struct smp2p_smem_item)); - rmp->remote_item.header.magic = SMP2P_MAGIC; - SMP2P_SET_LOCAL_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_REMOTE_MOCK_PROC); - SMP2P_SET_REMOTE_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_APPS_PROC); - SMP2P_SET_VERSION( - rmp->remote_item.header.feature_version, 1); - SMP2P_SET_FEATURES( - rmp->remote_item.header.feature_version, 0); - SMP2P_SET_ENT_TOTAL( - rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY); - SMP2P_SET_ENT_VALID( - rmp->remote_item.header.valid_total_ent, 0); - rmp->remote_item.header.flags = 0x0; - msm_smp2p_set_remote_mock_exists(true); - - /* Create Max Entries in the remote mock object */ - for (j = 0; j < SMP2P_MAX_ENTRY; j++) { - scnprintf(rmp->remote_item.entries[j].name, - SMP2P_MAX_ENTRY_NAME, "smp2p%d", j); - rmp->remote_item.entries[j].entry = 0; - rmp->tx_interrupt(); - } - - /* Register for in entries */ - for (j = 0; j < SMP2P_MAX_ENTRY; j++) { - ret = msm_smp2p_in_register(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[j].name, - &(cb_in[j].nb)); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &(cb_in[j].cb_completion), HZ / 2), - >, 0); - UT_ASSERT_INT(cb_in[j].cb_count, ==, 1); - UT_ASSERT_INT(cb_in[j].event_entry_update, ==, 0); - } - UT_ASSERT_INT(j, ==, SMP2P_MAX_ENTRY); - - /* Unregister */ - for (j = 0; j < SMP2P_MAX_ENTRY; j++) { - ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[j].name, - &(cb_in[j].nb)); - UT_ASSERT_INT(ret, ==, 0); - } - UT_ASSERT_INT(j, ==, SMP2P_MAX_ENTRY); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - - for (j = 0; j < SMP2P_MAX_ENTRY; j++) - ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[j].name, - &(cb_in[j].nb)); - } -} - -/** - * smp2p_ut_local_in_multiple - Verify Multiple Inbound Registration. - * - * @s: pointer to output file - * - * This test verifies multiple clients registering for same inbound entries - * using the remote mock processor. - */ -static void smp2p_ut_local_in_multiple(struct seq_file *s) -{ - int failed = 0; - struct msm_smp2p_remote_mock *rmp = NULL; - int ret; - static struct mock_cb_data cb_in_1; - static struct mock_cb_data cb_in_2; - static struct mock_cb_data cb_out; - - seq_printf(s, "Running %s\n", __func__); - - mock_cb_data_init(&cb_in_1); - mock_cb_data_init(&cb_in_2); - mock_cb_data_init(&cb_out); - - do { - /* Initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - rmp = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(rmp, !=, NULL); - - rmp->rx_interrupt_count = 0; - memset(&rmp->remote_item, 0, - sizeof(struct smp2p_smem_item)); - rmp->remote_item.header.magic = SMP2P_MAGIC; - SMP2P_SET_LOCAL_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_REMOTE_MOCK_PROC); - SMP2P_SET_REMOTE_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_APPS_PROC); - SMP2P_SET_VERSION( - rmp->remote_item.header.feature_version, 1); - SMP2P_SET_FEATURES( - rmp->remote_item.header.feature_version, 0); - SMP2P_SET_ENT_TOTAL( - rmp->remote_item.header.valid_total_ent, 1); - SMP2P_SET_ENT_VALID( - rmp->remote_item.header.valid_total_ent, 0); - rmp->remote_item.header.flags = 0x0; - msm_smp2p_set_remote_mock_exists(true); - - /* Create an Entry in the remote mock object */ - scnprintf(rmp->remote_item.entries[0].name, - SMP2P_MAX_ENTRY_NAME, "smp2p%d", 1); - rmp->remote_item.entries[0].entry = 0; - rmp->tx_interrupt(); - - /* Register multiple clients for the inbound entry */ - ret = msm_smp2p_in_register(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[0].name, - &cb_in_1.nb); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &(cb_in_1.cb_completion), HZ / 2), - >, 0); - UT_ASSERT_INT(cb_in_1.cb_count, ==, 1); - UT_ASSERT_INT(cb_in_1.event_entry_update, ==, 0); - - ret = msm_smp2p_in_register(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[0].name, - &cb_in_2.nb); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &(cb_in_2.cb_completion), HZ / 2), - >, 0); - UT_ASSERT_INT(cb_in_2.cb_count, ==, 1); - UT_ASSERT_INT(cb_in_2.event_entry_update, ==, 0); - - - /* Unregister the clients */ - ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[0].name, - &(cb_in_1.nb)); - UT_ASSERT_INT(ret, ==, 0); - - ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[0].name, - &(cb_in_2.nb)); - UT_ASSERT_INT(ret, ==, 0); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - - ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[0].name, - &(cb_in_1.nb)); - - ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[0].name, - &(cb_in_2.nb)); - } -} - -/** - * smp2p_ut_local_ssr_ack - Verify SSR Done/ACK Feature - * - * @s: pointer to output file - */ -static void smp2p_ut_local_ssr_ack(struct seq_file *s) -{ - int failed = 0; - struct msm_smp2p_remote_mock *rmp = NULL; - int ret; - - seq_printf(s, "Running %s\n", __func__); - do { - struct smp2p_smem *rhdr; - struct smp2p_smem *lhdr; - int negotiation_state; - - /* initialize v1 without SMP2P_FEATURE_SSR_ACK enabled */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - rmp = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(rmp, !=, NULL); - rhdr = &rmp->remote_item.header; - - rmp->rx_interrupt_count = 0; - memset(&rmp->remote_item, 0, sizeof(struct smp2p_smem_item)); - rhdr->magic = SMP2P_MAGIC; - SMP2P_SET_LOCAL_PID(rhdr->rem_loc_proc_id, - SMP2P_REMOTE_MOCK_PROC); - SMP2P_SET_REMOTE_PID(rhdr->rem_loc_proc_id, SMP2P_APPS_PROC); - SMP2P_SET_VERSION(rhdr->feature_version, 1); - SMP2P_SET_FEATURES(rhdr->feature_version, 0); - SMP2P_SET_ENT_TOTAL(rhdr->valid_total_ent, SMP2P_MAX_ENTRY); - SMP2P_SET_ENT_VALID(rhdr->valid_total_ent, 0); - rhdr->flags = 0x0; - msm_smp2p_set_remote_mock_exists(true); - rmp->tx_interrupt(); - - /* verify edge is open */ - lhdr = smp2p_get_out_item(SMP2P_REMOTE_MOCK_PROC, - &negotiation_state); - UT_ASSERT_PTR(NULL, !=, lhdr); - UT_ASSERT_INT(negotiation_state, ==, SMP2P_EDGE_STATE_OPENED); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - - /* verify no response to ack feature */ - rmp->rx_interrupt_count = 0; - SMP2P_SET_RESTART_DONE(rhdr->flags, 1); - rmp->tx_interrupt(); - UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_DONE(lhdr->flags)); - UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_ACK(lhdr->flags)); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 0); - - /* initialize v1 with SMP2P_FEATURE_SSR_ACK enabled */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - rmp = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(rmp, !=, NULL); - rhdr = &rmp->remote_item.header; - - rmp->rx_interrupt_count = 0; - memset(&rmp->remote_item, 0, sizeof(struct smp2p_smem_item)); - rhdr->magic = SMP2P_MAGIC; - SMP2P_SET_LOCAL_PID(rhdr->rem_loc_proc_id, - SMP2P_REMOTE_MOCK_PROC); - SMP2P_SET_REMOTE_PID(rhdr->rem_loc_proc_id, SMP2P_APPS_PROC); - SMP2P_SET_VERSION(rhdr->feature_version, 1); - SMP2P_SET_FEATURES(rhdr->feature_version, - SMP2P_FEATURE_SSR_ACK); - SMP2P_SET_ENT_TOTAL(rhdr->valid_total_ent, SMP2P_MAX_ENTRY); - SMP2P_SET_ENT_VALID(rhdr->valid_total_ent, 0); - rmp->rx_interrupt_count = 0; - rhdr->flags = 0x0; - msm_smp2p_set_remote_mock_exists(true); - rmp->tx_interrupt(); - - /* verify edge is open */ - lhdr = smp2p_get_out_item(SMP2P_REMOTE_MOCK_PROC, - &negotiation_state); - UT_ASSERT_PTR(NULL, !=, lhdr); - UT_ASSERT_INT(negotiation_state, ==, SMP2P_EDGE_STATE_OPENED); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - - /* verify response to ack feature */ - rmp->rx_interrupt_count = 0; - SMP2P_SET_RESTART_DONE(rhdr->flags, 1); - rmp->tx_interrupt(); - UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_DONE(lhdr->flags)); - UT_ASSERT_INT(1, ==, SMP2P_GET_RESTART_ACK(lhdr->flags)); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - - rmp->rx_interrupt_count = 0; - SMP2P_SET_RESTART_DONE(rhdr->flags, 0); - rmp->tx_interrupt(); - UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_DONE(lhdr->flags)); - UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_ACK(lhdr->flags)); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -/** - * get_ssr_name_for_proc - Retrieve an SSR name from the provided list - * - * @names: List of possible processor names - * @name_len: The length of @names - * @index: Index into @names - * - * Return: Pointer to the next processor name, NULL in error conditions - */ -static char *get_ssr_name_for_proc(char *names[], size_t name_len, int index) -{ - if (index >= name_len) { - pr_err("%s: SSR failed; check subsys name table\n", - __func__); - return NULL; - } - - return names[index]; -} - -/** - * smp2p_ut_local_ssr_ack - Verify SSR Done/ACK Feature - * - * @s: pointer to output file - * @rpid: Remote processor ID - * @int_cfg: Interrupt config - */ -static void smp2p_ut_remotesubsys_ssr_ack(struct seq_file *s, uint32_t rpid, - struct smp2p_interrupt_config *int_cfg) -{ - int failed = 0; - - seq_printf(s, "Running %s\n", __func__); - do { - struct smp2p_smem *rhdr; - struct smp2p_smem *lhdr; - int negotiation_state; - int name_index; - int ret; - uint32_t ssr_done_start; - bool ssr_ack_enabled = false; - bool ssr_success = false; - char *name = NULL; - - static char *mpss_names[] = {"modem", "mpss"}; - static char *lpass_names[] = {"adsp", "lpass"}; - static char *sensor_names[] = {"slpi", "dsps"}; - static char *wcnss_names[] = {"wcnss"}; - - lhdr = smp2p_get_out_item(rpid, &negotiation_state); - UT_ASSERT_PTR(NULL, !=, lhdr); - UT_ASSERT_INT(SMP2P_EDGE_STATE_OPENED, ==, negotiation_state); - - rhdr = smp2p_get_in_item(rpid); - UT_ASSERT_PTR(NULL, !=, rhdr); - - /* get initial state of SSR flags */ - if (SMP2P_GET_FEATURES(rhdr->feature_version) - & SMP2P_FEATURE_SSR_ACK) - ssr_ack_enabled = true; - else - ssr_ack_enabled = false; - - ssr_done_start = SMP2P_GET_RESTART_DONE(rhdr->flags); - UT_ASSERT_INT(ssr_done_start, ==, - SMP2P_GET_RESTART_ACK(lhdr->flags)); - - /* trigger restart */ - name_index = 0; - while (!ssr_success) { - - switch (rpid) { - case SMP2P_MODEM_PROC: - name = get_ssr_name_for_proc(mpss_names, - ARRAY_SIZE(mpss_names), - name_index); - break; - case SMP2P_AUDIO_PROC: - name = get_ssr_name_for_proc(lpass_names, - ARRAY_SIZE(lpass_names), - name_index); - break; - case SMP2P_SENSOR_PROC: - name = get_ssr_name_for_proc(sensor_names, - ARRAY_SIZE(sensor_names), - name_index); - break; - case SMP2P_WIRELESS_PROC: - name = get_ssr_name_for_proc(wcnss_names, - ARRAY_SIZE(wcnss_names), - name_index); - break; - default: - pr_err("%s: Invalid proc ID %d given for ssr\n", - __func__, rpid); - } - - if (!name) { - seq_puts(s, "\tSSR failed; check subsys name table\n"); - failed = true; - break; - } - - seq_printf(s, "Restarting '%s'\n", name); - ret = subsystem_restart(name); - if (ret == -ENODEV) { - seq_puts(s, "\tSSR call failed\n"); - ++name_index; - continue; - } - ssr_success = true; - } - if (failed) - break; - - msleep(10*1000); - - /* verify ack signaling */ - if (ssr_ack_enabled) { - ssr_done_start ^= 1; - UT_ASSERT_INT(ssr_done_start, ==, - SMP2P_GET_RESTART_ACK(lhdr->flags)); - UT_ASSERT_INT(ssr_done_start, ==, - SMP2P_GET_RESTART_DONE(rhdr->flags)); - UT_ASSERT_INT(0, ==, - SMP2P_GET_RESTART_DONE(lhdr->flags)); - seq_puts(s, "\tSSR ACK Enabled and Toggled\n"); - } else { - UT_ASSERT_INT(0, ==, - SMP2P_GET_RESTART_DONE(lhdr->flags)); - UT_ASSERT_INT(0, ==, - SMP2P_GET_RESTART_ACK(lhdr->flags)); - - UT_ASSERT_INT(0, ==, - SMP2P_GET_RESTART_DONE(rhdr->flags)); - UT_ASSERT_INT(0, ==, - SMP2P_GET_RESTART_ACK(rhdr->flags)); - seq_puts(s, "\tSSR ACK Disabled\n"); - } - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -/** - * smp2p_ut_remote_ssr_ack - Verify SSR Done/ACK Feature - * - * @s: pointer to output file - * - * Triggers SSR for each subsystem. - */ -static void smp2p_ut_remote_ssr_ack(struct seq_file *s) -{ - struct smp2p_interrupt_config *int_cfg; - int pid; - - int_cfg = smp2p_get_interrupt_config(); - if (!int_cfg) { - seq_puts(s, - "Remote processor config unavailable\n"); - return; - } - - for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) { - if (!int_cfg[pid].is_configured) - continue; - - msm_smp2p_deinit_rmt_lpb_proc(pid); - smp2p_ut_remotesubsys_ssr_ack(s, pid, &int_cfg[pid]); - msm_smp2p_init_rmt_lpb_proc(pid); - } -} - -static struct dentry *dent; -static DEFINE_MUTEX(show_lock); - -static int debugfs_show(struct seq_file *s, void *data) -{ - void (*show)(struct seq_file *) = s->private; - - mutex_lock(&show_lock); - show(s); - mutex_unlock(&show_lock); - - return 0; -} - -static int debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, debugfs_show, inode->i_private); -} - -static const struct file_operations debug_ops = { - .open = debug_open, - .release = single_release, - .read = seq_read, - .llseek = seq_lseek, -}; - -void smp2p_debug_create(const char *name, - void (*show)(struct seq_file *)) -{ - struct dentry *file; - - file = debugfs_create_file(name, 0444, dent, show, &debug_ops); - if (!file) - pr_err("%s: unable to create file '%s'\n", __func__, name); -} - -void smp2p_debug_create_u32(const char *name, uint32_t *value) -{ - struct dentry *file; - - file = debugfs_create_u32(name, S_IRUGO | S_IWUSR, dent, value); - if (!file) - pr_err("%s: unable to create file '%s'\n", __func__, name); -} - -static int __init smp2p_debugfs_init(void) -{ - dent = debugfs_create_dir("smp2p_test", 0); - if (IS_ERR(dent)) - return PTR_ERR(dent); - - /* - * Add Unit Test entries. - * - * The idea with unit tests is that you can run all of them - * from ADB shell by doing: - * adb shell - * cat ut* - * - * And if particular tests fail, you can then repeatedly run the - * failing tests as you debug and resolve the failing test. - */ - smp2p_debug_create("ut_local_basic", - smp2p_ut_local_basic); - smp2p_debug_create("ut_local_late_open", - smp2p_ut_local_late_open); - smp2p_debug_create("ut_local_early_open", - smp2p_ut_local_early_open); - smp2p_debug_create("ut_mock_loopback", - smp2p_ut_mock_loopback); - smp2p_debug_create("ut_remote_inout", - smp2p_ut_remote_inout); - smp2p_debug_create("ut_local_in_max_entries", - smp2p_ut_local_in_max_entries); - smp2p_debug_create("ut_remote_out_max_entries", - smp2p_ut_remote_out_max_entries); - smp2p_debug_create("ut_local_in_multiple", - smp2p_ut_local_in_multiple); - smp2p_debug_create("ut_local_ssr_ack", - smp2p_ut_local_ssr_ack); - smp2p_debug_create("ut_remote_ssr_ack", - smp2p_ut_remote_ssr_ack); - - return 0; -} -module_init(smp2p_debugfs_init); diff --git a/drivers/soc/qcom/smp2p_test_common.h b/drivers/soc/qcom/smp2p_test_common.h deleted file mode 100644 index 3be519bc0c96..000000000000 --- a/drivers/soc/qcom/smp2p_test_common.h +++ /dev/null @@ -1,214 +0,0 @@ -/* drivers/soc/qcom/smp2p_test_common.h - * - * 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. - * - * 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 _SMP2P_TEST_COMMON_H_ -#define _SMP2P_TEST_COMMON_H_ - -#include - -/** - * Unit test assertion for logging test cases. - * - * @a lval - * @b rval - * @cmp comparison operator - * - * Assertion fails if (@a cmp @b) is not true which then - * logs the function and line number where the error occurred - * along with the values of @a and @b. - * - * Assumes that the following local variables exist: - * @s - sequential output file pointer - * @failed - set to true if test fails - */ -#define UT_ASSERT_INT(a, cmp, b) \ - { \ - int a_tmp = (a); \ - int b_tmp = (b); \ - if (!((a_tmp)cmp(b_tmp))) { \ - seq_printf(s, "%s:%d Fail: " #a "(%d) " #cmp " " #b "(%d)\n", \ - __func__, __LINE__, \ - a_tmp, b_tmp); \ - failed = 1; \ - break; \ - } \ - } - -#define UT_ASSERT_PTR(a, cmp, b) \ - { \ - void *a_tmp = (a); \ - void *b_tmp = (b); \ - if (!((a_tmp)cmp(b_tmp))) { \ - seq_printf(s, "%s:%d Fail: " #a "(%pK) " #cmp \ - " " #b "(%pK)\n", \ - __func__, __LINE__, \ - a_tmp, b_tmp); \ - failed = 1; \ - break; \ - } \ - } - -#define UT_ASSERT_UINT(a, cmp, b) \ - { \ - unsigned a_tmp = (a); \ - unsigned b_tmp = (b); \ - if (!((a_tmp)cmp(b_tmp))) { \ - seq_printf(s, "%s:%d Fail: " #a "(%u) " #cmp " " #b "(%u)\n", \ - __func__, __LINE__, \ - a_tmp, b_tmp); \ - failed = 1; \ - break; \ - } \ - } - -#define UT_ASSERT_HEX(a, cmp, b) \ - { \ - unsigned a_tmp = (a); \ - unsigned b_tmp = (b); \ - if (!((a_tmp)cmp(b_tmp))) { \ - seq_printf(s, "%s:%d Fail: " #a "(%x) " #cmp " " #b "(%x)\n", \ - __func__, __LINE__, \ - a_tmp, b_tmp); \ - failed = 1; \ - break; \ - } \ - } - -/** - * In-range unit test assertion for test cases. - * - * @a lval - * @minv Minimum value - * @maxv Maximum value - * - * Assertion fails if @a is not on the exclusive range minv, maxv - * ((@a < @minv) or (@a > @maxv)). In the failure case, the macro - * logs the function and line number where the error occurred along - * with the values of @a and @minv, @maxv. - * - * Assumes that the following local variables exist: - * @s - sequential output file pointer - * @failed - set to true if test fails - */ -#define UT_ASSERT_INT_IN_RANGE(a, minv, maxv) \ - { \ - int a_tmp = (a); \ - int minv_tmp = (minv); \ - int maxv_tmp = (maxv); \ - if (((a_tmp) < (minv_tmp)) || ((a_tmp) > (maxv_tmp))) { \ - seq_printf(s, "%s:%d Fail: " #a "(%d) < " #minv "(%d) or " \ - #a "(%d) > " #maxv "(%d)\n", \ - __func__, __LINE__, \ - a_tmp, minv_tmp, a_tmp, maxv_tmp); \ - failed = 1; \ - break; \ - } \ - } - -/* Structure to track state changes for the notifier callback. */ -struct mock_cb_data { - bool initialized; - spinlock_t lock; - struct notifier_block nb; - - /* events */ - struct completion cb_completion; - int cb_count; - int event_open; - int event_entry_update; - struct msm_smp2p_update_notif entry_data; -}; - -void smp2p_debug_create(const char *name, void (*show)(struct seq_file *)); -void smp2p_debug_create_u32(const char *name, uint32_t *value); -static inline int smp2p_test_notify(struct notifier_block *self, - unsigned long event, void *data); - -/** - * Reset mock callback data to default values. - * - * @cb: Mock callback data - */ -static inline void mock_cb_data_reset(struct mock_cb_data *cb) -{ - reinit_completion(&cb->cb_completion); - cb->cb_count = 0; - cb->event_open = 0; - cb->event_entry_update = 0; - memset(&cb->entry_data, 0, - sizeof(struct msm_smp2p_update_notif)); -} - - -/** - * Initialize mock callback data. - * - * @cb: Mock callback data - */ -static inline void mock_cb_data_init(struct mock_cb_data *cb) -{ - if (!cb->initialized) { - init_completion(&cb->cb_completion); - spin_lock_init(&cb->lock); - cb->initialized = true; - cb->nb.notifier_call = smp2p_test_notify; - memset(&cb->entry_data, 0, - sizeof(struct msm_smp2p_update_notif)); - } - mock_cb_data_reset(cb); -} - -/** - * Notifier function passed into SMP2P for testing. - * - * @self: Pointer to calling notifier block - * @event: Event - * @data: Event-specific data - * @returns: 0 - */ -static inline int smp2p_test_notify(struct notifier_block *self, - unsigned long event, void *data) -{ - struct mock_cb_data *cb_data_ptr; - unsigned long flags; - - cb_data_ptr = container_of(self, struct mock_cb_data, nb); - - spin_lock_irqsave(&cb_data_ptr->lock, flags); - - switch (event) { - case SMP2P_OPEN: - ++cb_data_ptr->event_open; - if (data) { - cb_data_ptr->entry_data = - *(struct msm_smp2p_update_notif *)(data); - } - break; - case SMP2P_ENTRY_UPDATE: - ++cb_data_ptr->event_entry_update; - if (data) { - cb_data_ptr->entry_data = - *(struct msm_smp2p_update_notif *)(data); - } - break; - default: - pr_err("%s Unknown event\n", __func__); - break; - } - - ++cb_data_ptr->cb_count; - complete(&cb_data_ptr->cb_completion); - spin_unlock_irqrestore(&cb_data_ptr->lock, flags); - return 0; -} -#endif /* _SMP2P_TEST_COMMON_H_ */ From d1adc60b721fba3422cb69ba04d63206b3709d69 Mon Sep 17 00:00:00 2001 From: Hardik Arya Date: Wed, 10 Oct 2018 18:25:49 +0530 Subject: [PATCH 32/75] soc: qcom: Remove smp2p test support Smp2p test code is used internally to test the functionality of drivers and has no real use case in end product. Change-Id: I7a50c077bb71068188b5411424c5782b3d0edbb7 Signed-off-by: Hardik Arya --- drivers/gpio/Makefile | 1 - drivers/gpio/gpio-msm-smp2p-test.c | 762 -------------- drivers/soc/qcom/Makefile | 3 +- drivers/soc/qcom/smp2p_spinlock_test.c | 819 --------------- drivers/soc/qcom/smp2p_test.c | 1327 ------------------------ drivers/soc/qcom/smp2p_test_common.h | 214 ---- 6 files changed, 1 insertion(+), 3125 deletions(-) delete mode 100644 drivers/gpio/gpio-msm-smp2p-test.c delete mode 100644 drivers/soc/qcom/smp2p_spinlock_test.c delete mode 100644 drivers/soc/qcom/smp2p_test.c delete mode 100644 drivers/soc/qcom/smp2p_test_common.h diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ac55dd34cfcb..7f2acfabf86d 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -121,4 +121,3 @@ obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o obj-$(CONFIG_GPIO_ZX) += gpio-zx.o obj-$(CONFIG_MSM_SMP2P) += gpio-msm-smp2p.o -obj-$(CONFIG_MSM_SMP2P_TEST) += gpio-msm-smp2p-test.o diff --git a/drivers/gpio/gpio-msm-smp2p-test.c b/drivers/gpio/gpio-msm-smp2p-test.c deleted file mode 100644 index 5907513b43c0..000000000000 --- a/drivers/gpio/gpio-msm-smp2p-test.c +++ /dev/null @@ -1,762 +0,0 @@ -/* drivers/gpio/gpio-msm-smp2p-test.c - * - * 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 - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../soc/qcom/smp2p_private.h" -#include "../soc/qcom/smp2p_test_common.h" - -/* Interrupt callback data */ -struct gpio_info { - int gpio_base_id; - int irq_base_id; - - bool initialized; - struct completion cb_completion; - int cb_count; - DECLARE_BITMAP(triggered_irqs, SMP2P_BITS_PER_ENTRY); -}; - -/* GPIO Inbound/Outbound callback info */ -struct gpio_inout { - struct gpio_info in; - struct gpio_info out; -}; - -static struct gpio_inout gpio_info[SMP2P_NUM_PROCS]; - -/** - * Init/reset the callback data. - * - * @info: Pointer to callback data - */ -static void cb_data_reset(struct gpio_info *info) -{ - int n; - - if (!info) - return; - - if (!info->initialized) { - init_completion(&info->cb_completion); - info->initialized = true; - } - info->cb_count = 0; - - for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) - clear_bit(n, info->triggered_irqs); - - reinit_completion(&info->cb_completion); -} - -static int smp2p_gpio_test_probe(struct platform_device *pdev) -{ - int id; - int cnt; - struct device_node *node = pdev->dev.of_node; - struct gpio_info *gpio_info_ptr = NULL; - - /* - * NOTE: This does a string-lookup of the GPIO pin name and doesn't - * actually directly link to the SMP2P GPIO driver since all - * GPIO/Interrupt access must be through standard - * Linux GPIO / Interrupt APIs. - */ - if (strcmp("qcom,smp2pgpio_test_smp2p_1_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_MODEM_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_1_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_MODEM_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_2_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_AUDIO_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_2_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_AUDIO_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_3_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_SENSOR_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_3_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_SENSOR_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_4_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_WIRELESS_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_4_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_WIRELESS_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_5_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_CDSP_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_5_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_CDSP_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_7_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_TZ_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_7_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_TZ_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_15_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in; - } else if ( - strcmp("qcom,smp2pgpio_test_smp2p_15_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_REMOTE_MOCK_PROC].out; - } else { - pr_err("%s: unable to match device type '%s'\n", - __func__, node->name); - return -ENODEV; - } - - /* retrieve the GPIO and interrupt ID's */ - cnt = of_gpio_count(node); - if (cnt && gpio_info_ptr) { - /* - * Instead of looping through all 32-bits, we can just get the - * first pin to get the base IDs. This saves on the verbosity - * of the device tree nodes as well. - */ - id = of_get_gpio(node, 0); - if (id == -EPROBE_DEFER) - return id; - gpio_info_ptr->gpio_base_id = id; - gpio_info_ptr->irq_base_id = gpio_to_irq(id); - } - return 0; -} - -/* - * NOTE: Instead of match table and device driver, you may be able to just - * call of_find_compatible_node() in your init function. - */ -static struct of_device_id msm_smp2p_match_table[] = { - /* modem */ - {.compatible = "qcom,smp2pgpio_test_smp2p_1_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_1_in", }, - - /* audio (adsp) */ - {.compatible = "qcom,smp2pgpio_test_smp2p_2_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_2_in", }, - - /* sensor */ - {.compatible = "qcom,smp2pgpio_test_smp2p_3_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_3_in", }, - - /* wcnss */ - {.compatible = "qcom,smp2pgpio_test_smp2p_4_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_4_in", }, - - /* CDSP */ - {.compatible = "qcom,smp2pgpio_test_smp2p_5_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_5_in", }, - - /* TZ */ - {.compatible = "qcom,smp2pgpio_test_smp2p_7_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_7_in", }, - - /* mock loopback */ - {.compatible = "qcom,smp2pgpio_test_smp2p_15_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_15_in", }, - {}, -}; - -static struct platform_driver smp2p_gpio_driver = { - .probe = smp2p_gpio_test_probe, - .driver = { - .name = "smp2pgpio_test", - .owner = THIS_MODULE, - .of_match_table = msm_smp2p_match_table, - }, -}; - -/** - * smp2p_ut_local_gpio_out - Verify outbound functionality. - * - * @s: pointer to output file - */ -static void smp2p_ut_local_gpio_out(struct seq_file *s) -{ - int failed = 0; - struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].out; - int ret; - int id; - struct msm_smp2p_remote_mock *mock; - - seq_printf(s, "Running %s\n", __func__); - do { - /* initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - mock = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(mock, !=, NULL); - - mock->rx_interrupt_count = 0; - memset(&mock->remote_item, 0, - sizeof(struct smp2p_smem_item)); - smp2p_init_header((struct smp2p_smem *)&mock->remote_item, - SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC, - 0, 1); - strlcpy(mock->remote_item.entries[0].name, "smp2p", - SMP2P_MAX_ENTRY_NAME); - SMP2P_SET_ENT_VALID( - mock->remote_item.header.valid_total_ent, 1); - msm_smp2p_set_remote_mock_exists(true); - mock->tx_interrupt(); - - /* open GPIO entry */ - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, true); - - /* verify set/get functions */ - UT_ASSERT_INT(0, <, cb_info->gpio_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - int pin = cb_info->gpio_base_id + id; - - mock->rx_interrupt_count = 0; - gpio_set_value(pin, 1); - UT_ASSERT_INT(1, ==, mock->rx_interrupt_count); - UT_ASSERT_INT(1, ==, gpio_get_value(pin)); - - gpio_set_value(pin, 0); - UT_ASSERT_INT(2, ==, mock->rx_interrupt_count); - UT_ASSERT_INT(0, ==, gpio_get_value(pin)); - } - if (failed) - break; - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } - - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, false); -} - -/** - * smp2p_gpio_irq - Interrupt handler for inbound entries. - * - * @irq: Virtual IRQ being triggered - * @data: Cookie data (struct gpio_info * in this case) - * @returns: Number of bytes written - */ -static irqreturn_t smp2p_gpio_irq(int irq, void *data) -{ - struct gpio_info *gpio_ptr = (struct gpio_info *)data; - int offset; - - if (!gpio_ptr) { - pr_err("%s: gpio_ptr is NULL for irq %d\n", __func__, irq); - return IRQ_HANDLED; - } - - offset = irq - gpio_ptr->irq_base_id; - if (offset >= 0 && offset < SMP2P_BITS_PER_ENTRY) - set_bit(offset, gpio_ptr->triggered_irqs); - else - pr_err("%s: invalid irq offset base %d; irq %d\n", - __func__, gpio_ptr->irq_base_id, irq); - - ++gpio_ptr->cb_count; - complete(&gpio_ptr->cb_completion); - return IRQ_HANDLED; -} - -/** - * smp2p_ut_local_gpio_in - Verify inbound functionality. - * - * @s: pointer to output file - */ -static void smp2p_ut_local_gpio_in(struct seq_file *s) -{ - int failed = 0; - struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in; - int id; - int ret; - int virq; - struct msm_smp2p_remote_mock *mock; - - seq_printf(s, "Running %s\n", __func__); - - cb_data_reset(cb_info); - do { - /* initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - mock = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(mock, !=, NULL); - - mock->rx_interrupt_count = 0; - memset(&mock->remote_item, 0, - sizeof(struct smp2p_smem_item)); - smp2p_init_header((struct smp2p_smem *)&mock->remote_item, - SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC, - 0, 1); - strlcpy(mock->remote_item.entries[0].name, "smp2p", - SMP2P_MAX_ENTRY_NAME); - SMP2P_SET_ENT_VALID( - mock->remote_item.header.valid_total_ent, 1); - msm_smp2p_set_remote_mock_exists(true); - mock->tx_interrupt(); - - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, true); - - /* verify set/get functions locally */ - UT_ASSERT_INT(0, <, cb_info->gpio_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - int pin; - int current_value; - - /* verify pin value cannot be set */ - pin = cb_info->gpio_base_id + id; - current_value = gpio_get_value(pin); - - gpio_set_value(pin, 0); - UT_ASSERT_INT(current_value, ==, gpio_get_value(pin)); - gpio_set_value(pin, 1); - UT_ASSERT_INT(current_value, ==, gpio_get_value(pin)); - - /* verify no interrupts */ - UT_ASSERT_INT(0, ==, cb_info->cb_count); - } - if (failed) - break; - - /* register for interrupts */ - UT_ASSERT_INT(0, <, cb_info->irq_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq)); - ret = request_irq(virq, - smp2p_gpio_irq, IRQF_TRIGGER_RISING, - "smp2p_test", cb_info); - UT_ASSERT_INT(0, ==, ret); - } - if (failed) - break; - - /* verify both rising and falling edge interrupts */ - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - irq_set_irq_type(virq, IRQ_TYPE_EDGE_BOTH); - cb_data_reset(cb_info); - - /* verify rising-edge interrupt */ - mock->remote_item.entries[0].entry = 1 << id; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 1); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - test_bit(id, cb_info->triggered_irqs); - - /* verify falling-edge interrupt */ - mock->remote_item.entries[0].entry = 0; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 2); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - } - if (failed) - break; - - /* verify rising-edge interrupts */ - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING); - cb_data_reset(cb_info); - - /* verify only rising-edge interrupt is triggered */ - mock->remote_item.entries[0].entry = 1 << id; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 1); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - test_bit(id, cb_info->triggered_irqs); - - mock->remote_item.entries[0].entry = 0; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 1); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - } - if (failed) - break; - - /* verify falling-edge interrupts */ - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - irq_set_irq_type(virq, IRQ_TYPE_EDGE_FALLING); - cb_data_reset(cb_info); - - /* verify only rising-edge interrupt is triggered */ - mock->remote_item.entries[0].entry = 1 << id; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 0); - UT_ASSERT_INT(0, ==, - test_bit(id, cb_info->triggered_irqs)); - - mock->remote_item.entries[0].entry = 0; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 1); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - } - if (failed) - break; - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } - - /* unregister for interrupts */ - if (cb_info->irq_base_id) { - for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id) - free_irq(cb_info->irq_base_id + id, cb_info); - } - - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, false); -} - -/** - * smp2p_ut_local_gpio_in_update_open - Verify combined open/update. - * - * @s: pointer to output file - * - * If the remote side updates the SMP2P bits and sends before negotiation is - * complete, then the UPDATE event will have to be delayed until negotiation is - * complete. This should result in both the OPEN and UPDATE events coming in - * right after each other and the behavior should be transparent to the clients - * of SMP2P GPIO. - */ -static void smp2p_ut_local_gpio_in_update_open(struct seq_file *s) -{ - int failed = 0; - struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in; - int id; - int ret; - int virq; - struct msm_smp2p_remote_mock *mock; - - seq_printf(s, "Running %s\n", __func__); - - cb_data_reset(cb_info); - do { - /* initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - mock = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(mock, !=, NULL); - - mock->rx_interrupt_count = 0; - memset(&mock->remote_item, 0, - sizeof(struct smp2p_smem_item)); - smp2p_init_header((struct smp2p_smem *)&mock->remote_item, - SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC, - 0, 1); - strlcpy(mock->remote_item.entries[0].name, "smp2p", - SMP2P_MAX_ENTRY_NAME); - SMP2P_SET_ENT_VALID( - mock->remote_item.header.valid_total_ent, 1); - - /* register for interrupts */ - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, true); - - UT_ASSERT_INT(0, <, cb_info->irq_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq)); - ret = request_irq(virq, - smp2p_gpio_irq, IRQ_TYPE_EDGE_BOTH, - "smp2p_test", cb_info); - UT_ASSERT_INT(0, ==, ret); - } - if (failed) - break; - - /* update the state value and complete negotiation */ - mock->remote_item.entries[0].entry = 0xDEADDEAD; - msm_smp2p_set_remote_mock_exists(true); - mock->tx_interrupt(); - - /* verify delayed state updates were processed */ - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - - UT_ASSERT_INT(cb_info->cb_count, >, 0); - if (0x1 & (0xDEADDEAD >> id)) { - /* rising edge should have been triggered */ - if (!test_bit(id, cb_info->triggered_irqs)) { - seq_printf(s, "%s:%d bit %d clear, ", - __func__, __LINE__, id); - seq_puts(s, "expected set\n"); - failed = 1; - break; - } - } else { - /* edge should not have been triggered */ - if (test_bit(id, cb_info->triggered_irqs)) { - seq_printf(s, "%s:%d bit %d set, ", - __func__, __LINE__, id); - seq_puts(s, "expected clear\n"); - failed = 1; - break; - } - } - } - if (failed) - break; - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } - - /* unregister for interrupts */ - if (cb_info->irq_base_id) { - for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id) - free_irq(cb_info->irq_base_id + id, cb_info); - } - - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, false); -} - -/** - * smp2p_gpio_write_bits - writes value to each GPIO pin specified in mask. - * - * @gpio: gpio test structure - * @mask: 1 = write gpio_value to this GPIO pin - * @gpio_value: value to write to GPIO pin - */ -static void smp2p_gpio_write_bits(struct gpio_info *gpio, uint32_t mask, - int gpio_value) -{ - int n; - - for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) { - if (mask & 0x1) - gpio_set_value(gpio->gpio_base_id + n, gpio_value); - mask >>= 1; - } -} - -static void smp2p_gpio_set_bits(struct gpio_info *gpio, uint32_t mask) -{ - smp2p_gpio_write_bits(gpio, mask, 1); -} - -static void smp2p_gpio_clr_bits(struct gpio_info *gpio, uint32_t mask) -{ - smp2p_gpio_write_bits(gpio, mask, 0); -} - -/** - * smp2p_gpio_get_value - reads entire 32-bits of GPIO - * - * @gpio: gpio structure - * @returns: 32 bit value of GPIO pins - */ -static uint32_t smp2p_gpio_get_value(struct gpio_info *gpio) -{ - int n; - uint32_t value = 0; - - for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) { - if (gpio_get_value(gpio->gpio_base_id + n)) - value |= 1 << n; - } - return value; -} - -/** - * smp2p_ut_remote_inout_core - Verify inbound/outbound functionality. - * - * @s: pointer to output file - * @remote_pid: Remote processor to test - * @name: Name of the test for reporting - * - * This test verifies inbound/outbound functionality for the remote processor. - */ -static void smp2p_ut_remote_inout_core(struct seq_file *s, int remote_pid, - const char *name) -{ - int failed = 0; - uint32_t request; - uint32_t response; - struct gpio_info *cb_in; - struct gpio_info *cb_out; - int id; - int ret; - - seq_printf(s, "Running %s for '%s' remote pid %d\n", - __func__, smp2p_pid_to_name(remote_pid), remote_pid); - - cb_in = &gpio_info[remote_pid].in; - cb_out = &gpio_info[remote_pid].out; - cb_data_reset(cb_in); - cb_data_reset(cb_out); - do { - /* open test entries */ - msm_smp2p_deinit_rmt_lpb_proc(remote_pid); - smp2p_gpio_open_test_entry("smp2p", remote_pid, true); - - /* register for interrupts */ - UT_ASSERT_INT(0, <, cb_in->gpio_base_id); - UT_ASSERT_INT(0, <, cb_in->irq_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - int virq = cb_in->irq_base_id + id; - UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq)); - ret = request_irq(virq, - smp2p_gpio_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "smp2p_test", cb_in); - UT_ASSERT_INT(0, ==, ret); - } - if (failed) - break; - - /* write echo of data value 0 */ - UT_ASSERT_INT(0, <, cb_out->gpio_base_id); - request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(request, 1); - SMP2P_SET_RMT_CMD(request, SMP2P_LB_CMD_ECHO); - SMP2P_SET_RMT_DATA(request, 0x0); - - smp2p_gpio_set_bits(cb_out, SMP2P_RMT_IGNORE_MASK); - smp2p_gpio_clr_bits(cb_out, ~SMP2P_RMT_IGNORE_MASK); - smp2p_gpio_set_bits(cb_out, request); - - UT_ASSERT_INT(cb_in->cb_count, ==, 0); - smp2p_gpio_clr_bits(cb_out, SMP2P_RMT_IGNORE_MASK); - - /* verify response */ - do { - /* wait for up to 32 changes */ - if (wait_for_completion_timeout( - &cb_in->cb_completion, HZ / 2) == 0) - break; - reinit_completion(&cb_in->cb_completion); - } while (cb_in->cb_count < 32); - UT_ASSERT_INT(cb_in->cb_count, >, 0); - response = smp2p_gpio_get_value(cb_in); - SMP2P_SET_RMT_CMD_TYPE(request, 0); - UT_ASSERT_HEX(request, ==, response); - - /* write echo of data value of all 1's */ - request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(request, 1); - SMP2P_SET_RMT_CMD(request, SMP2P_LB_CMD_ECHO); - SMP2P_SET_RMT_DATA(request, ~0); - - smp2p_gpio_set_bits(cb_out, SMP2P_RMT_IGNORE_MASK); - cb_data_reset(cb_in); - smp2p_gpio_clr_bits(cb_out, ~SMP2P_RMT_IGNORE_MASK); - smp2p_gpio_set_bits(cb_out, request); - - UT_ASSERT_INT(cb_in->cb_count, ==, 0); - smp2p_gpio_clr_bits(cb_out, SMP2P_RMT_IGNORE_MASK); - - /* verify response including 24 interrupts */ - do { - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in->cb_completion, HZ / 2), - >, 0); - reinit_completion(&cb_in->cb_completion); - } while (cb_in->cb_count < 24); - response = smp2p_gpio_get_value(cb_in); - SMP2P_SET_RMT_CMD_TYPE(request, 0); - UT_ASSERT_HEX(request, ==, response); - UT_ASSERT_INT(24, ==, cb_in->cb_count); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", name); - seq_puts(s, "\tFailed\n"); - } - - /* unregister for interrupts */ - if (cb_in->irq_base_id) { - for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id) - free_irq(cb_in->irq_base_id + id, cb_in); - } - - smp2p_gpio_open_test_entry("smp2p", remote_pid, false); - msm_smp2p_init_rmt_lpb_proc(remote_pid); -} - -/** - * smp2p_ut_remote_inout - Verify inbound/outbound functionality for all. - * - * @s: pointer to output file - * - * This test verifies inbound and outbound functionality for all - * configured remote processor. - */ -static void smp2p_ut_remote_inout(struct seq_file *s) -{ - struct smp2p_interrupt_config *int_cfg; - int pid; - - int_cfg = smp2p_get_interrupt_config(); - if (!int_cfg) { - seq_puts(s, "Remote processor config unavailable\n"); - return; - } - - for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) { - if (!int_cfg[pid].is_configured) - continue; - - smp2p_ut_remote_inout_core(s, pid, __func__); - } -} - -static int __init smp2p_debugfs_init(void) -{ - /* register GPIO pins */ - (void)platform_driver_register(&smp2p_gpio_driver); - - /* - * Add Unit Test entries. - * - * The idea with unit tests is that you can run all of them - * from ADB shell by doing: - * adb shell - * cat ut* - * - * And if particular tests fail, you can then repeatedly run the - * failing tests as you debug and resolve the failing test. - */ - smp2p_debug_create("ut_local_gpio_out", smp2p_ut_local_gpio_out); - smp2p_debug_create("ut_local_gpio_in", smp2p_ut_local_gpio_in); - smp2p_debug_create("ut_local_gpio_in_update_open", - smp2p_ut_local_gpio_in_update_open); - smp2p_debug_create("ut_remote_gpio_inout", smp2p_ut_remote_inout); - return 0; -} -late_initcall(smp2p_debugfs_init); diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 5e565c863889..7dff5d3b8d72 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -15,8 +15,7 @@ obj-$(CONFIG_MSM_GLINK_SPI_XPRT) += glink_spi_xprt.o obj-$(CONFIG_MSM_SMEM_LOGGING) += smem_log.o obj-$(CONFIG_MSM_SYSMON_GLINK_COMM) += sysmon-glink.o sysmon-qmi.o obj-$(CONFIG_ARCH_MSM8996) += kryo-l2-accessors.o -obj-$(CONFIG_MSM_SMP2P) += smp2p.o smp2p_debug.o smp2p_sleepstate.o -obj-$(CONFIG_MSM_SMP2P_TEST) += smp2p_loopback.o smp2p_test.o smp2p_spinlock_test.o +obj-$(CONFIG_MSM_SMP2P) += smp2p.o smp2p_loopback.o smp2p_debug.o smp2p_sleepstate.o obj-$(CONFIG_MSM_QMI_INTERFACE) += qmi_interface.o obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd.o obj-$(CONFIG_MSM_HVC) += hvc.o diff --git a/drivers/soc/qcom/smp2p_spinlock_test.c b/drivers/soc/qcom/smp2p_spinlock_test.c deleted file mode 100644 index 1fe4411eebde..000000000000 --- a/drivers/soc/qcom/smp2p_spinlock_test.c +++ /dev/null @@ -1,819 +0,0 @@ -/* drivers/soc/qcom/smp2p_spinlock_test.c - * - * 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 - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "smem_private.h" -#include "smp2p_private.h" -#include "smp2p_test_common.h" - -#define RS_END_THIEF_PID_BIT 20 -#define RS_END_THIEF_MASK 0x00f00000 - -/* Spinlock commands used for testing Apps<->RPM spinlocks. */ -enum RPM_SPINLOCK_CMDS { - RPM_CMD_INVALID, - RPM_CMD_START, - RPM_CMD_LOCKED, - RPM_CMD_UNLOCKED, - RPM_CMD_END, -}; - -/* Shared structure for testing Apps<->RPM spinlocks. */ -struct rpm_spinlock_test { - uint32_t apps_cmd; - uint32_t apps_lock_count; - uint32_t rpm_cmd; - uint32_t rpm_lock_count; -}; - -static uint32_t ut_remote_spinlock_run_time = 1; - -/** - * smp2p_ut_remote_spinlock_core - Verify remote spinlock. - * - * @s: Pointer to output file - * @remote_pid: Remote processor to test - * @use_trylock: Use trylock to prevent an Apps deadlock if the - * remote spinlock fails. - */ -static void smp2p_ut_remote_spinlock_core(struct seq_file *s, int remote_pid, - bool use_trylock) -{ - int failed = 0; - unsigned lock_count = 0; - struct msm_smp2p_out *handle = NULL; - int ret; - uint32_t test_request; - uint32_t test_response; - struct mock_cb_data cb_out; - struct mock_cb_data cb_in; - unsigned long flags; - unsigned n; - bool have_lock; - bool timeout; - int failed_tmp; - int spinlock_owner; - remote_spinlock_t *smem_spinlock; - unsigned long end; - - seq_printf(s, "Running %s for '%s' remote pid %d\n", - __func__, smp2p_pid_to_name(remote_pid), remote_pid); - - cb_out.initialized = false; - cb_in.initialized = false; - mock_cb_data_init(&cb_out); - mock_cb_data_init(&cb_in); - do { - smem_spinlock = smem_get_remote_spinlock(); - UT_ASSERT_PTR(smem_spinlock, !=, NULL); - - /* Open output entry */ - ret = msm_smp2p_out_open(remote_pid, SMP2P_RLPB_ENTRY_NAME, - &cb_out.nb, &handle); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_out.cb_completion, HZ * 2), - >, 0); - UT_ASSERT_INT(cb_out.cb_count, ==, 1); - UT_ASSERT_INT(cb_out.event_open, ==, 1); - - /* Open inbound entry */ - ret = msm_smp2p_in_register(remote_pid, SMP2P_RLPB_ENTRY_NAME, - &cb_in.nb); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ * 2), - >, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 1); - UT_ASSERT_INT(cb_in.event_open, ==, 1); - - /* Send start */ - mock_cb_data_reset(&cb_in); - mock_cb_data_reset(&cb_out); - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE_REQ(test_request); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_START); - SMP2P_SET_RMT_DATA(test_request, 0x0); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_INT(ret, ==, 0); - - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ * 2), - >, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 1); - UT_ASSERT_INT(cb_in.event_entry_update, ==, 1); - ret = msm_smp2p_in_read(remote_pid, SMP2P_RLPB_ENTRY_NAME, - &test_response); - UT_ASSERT_INT(ret, ==, 0); - - test_response = SMP2P_GET_RMT_CMD(test_response); - if (test_response != SMP2P_LB_CMD_RSPIN_LOCKED && - test_response != SMP2P_LB_CMD_RSPIN_UNLOCKED) { - /* invalid response from remote - abort test */ - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, 0x0); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_HEX(SMP2P_LB_CMD_RSPIN_LOCKED, ==, - test_response); - } - - /* Run spinlock test */ - if (use_trylock) - seq_puts(s, "\tUsing remote_spin_trylock\n"); - else - seq_puts(s, "\tUsing remote_spin_lock\n"); - - flags = 0; - have_lock = false; - timeout = false; - spinlock_owner = 0; - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE_REQ(test_request); - end = jiffies + (ut_remote_spinlock_run_time * HZ); - if (ut_remote_spinlock_run_time < 300) { - seq_printf(s, "\tRunning test for %u seconds; ", - ut_remote_spinlock_run_time); - seq_puts(s, - "on physical hardware please run >= 300 seconds by doing 'echo 300 > ut_remote_spinlock_time'\n"); - } - while (time_is_after_jiffies(end)) { - /* try to acquire spinlock */ - if (use_trylock) { - unsigned long j_start = jiffies; - while (!remote_spin_trylock_irqsave( - smem_spinlock, flags)) { - if (jiffies_to_msecs(jiffies - j_start) - > 1000) { - seq_puts(s, - "\tFail: Timeout trying to get the lock\n"); - timeout = true; - break; - } - } - if (timeout) - break; - } else { - remote_spin_lock_irqsave(smem_spinlock, flags); - } - have_lock = true; - ++lock_count; - - /* tell the remote side that we have the lock */ - SMP2P_SET_RMT_DATA(test_request, lock_count); - SMP2P_SET_RMT_CMD(test_request, - SMP2P_LB_CMD_RSPIN_LOCKED); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_INT(ret, ==, 0); - - /* verify the other side doesn't say it has the lock */ - for (n = 0; n < 1000; ++n) { - spinlock_owner = - remote_spin_owner(smem_spinlock); - if (spinlock_owner != SMEM_APPS) { - /* lock stolen by remote side */ - seq_puts(s, "\tFail: Remote side: "); - seq_printf(s, "%d stole lock pid: %d\n", - remote_pid, spinlock_owner); - failed = true; - break; - } - spinlock_owner = 0; - - ret = msm_smp2p_in_read(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &test_response); - UT_ASSERT_INT(ret, ==, 0); - test_response = - SMP2P_GET_RMT_CMD(test_response); - UT_ASSERT_HEX(SMP2P_LB_CMD_RSPIN_UNLOCKED, ==, - test_response); - } - if (failed) - break; - - /* tell remote side we are unlocked and release lock */ - SMP2P_SET_RMT_CMD(test_request, - SMP2P_LB_CMD_RSPIN_UNLOCKED); - (void)msm_smp2p_out_write(handle, test_request); - have_lock = false; - remote_spin_unlock_irqrestore(smem_spinlock, flags); - } - if (have_lock) - remote_spin_unlock_irqrestore(smem_spinlock, flags); - - /* End test */ - mock_cb_data_reset(&cb_in); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, lock_count | - (spinlock_owner << RS_END_THIEF_PID_BIT)); - (void)msm_smp2p_out_write(handle, test_request); - - failed_tmp = failed; - failed = false; - do { - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ * 2), - >, 0); - reinit_completion(&cb_in.cb_completion); - ret = msm_smp2p_in_read(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &test_response); - UT_ASSERT_INT(ret, ==, 0); - } while (!failed && - SMP2P_GET_RMT_CMD(test_response) != - SMP2P_LB_CMD_RSPIN_END); - if (failed) - break; - failed = failed_tmp; - - test_response = SMP2P_GET_RMT_DATA(test_response); - seq_puts(s, "\tLocked spinlock "); - seq_printf(s, "local %u times; remote %u times", - lock_count, - test_response & ((1 << RS_END_THIEF_PID_BIT) - 1) - ); - if (test_response & RS_END_THIEF_MASK) { - seq_puts(s, "Remote side reporting lock stolen by "); - seq_printf(s, "pid %d.\n", - SMP2P_GET_BITS(test_response, - RS_END_THIEF_MASK, - RS_END_THIEF_PID_BIT)); - failed = 1; - } - seq_puts(s, "\n"); - - /* Cleanup */ - ret = msm_smp2p_out_close(&handle); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_PTR(handle, ==, NULL); - ret = msm_smp2p_in_unregister(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &cb_in.nb); - UT_ASSERT_INT(ret, ==, 0); - - if (!failed && !timeout) - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - if (handle) { - /* send end command */ - test_request = 0; - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, lock_count); - (void)msm_smp2p_out_write(handle, test_request); - (void)msm_smp2p_out_close(&handle); - } - (void)msm_smp2p_in_unregister(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &cb_in.nb); - - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -/** - * smp2p_ut_remote_spinlock_pid - Verify remote spinlock for a processor. - * - * @s: Pointer to output file - * @pid: Processor to test - * @use_trylock: Use trylock to prevent an Apps deadlock if the - * remote spinlock fails. - */ -static void smp2p_ut_remote_spinlock_pid(struct seq_file *s, int pid, - bool use_trylock) -{ - struct smp2p_interrupt_config *int_cfg; - - int_cfg = smp2p_get_interrupt_config(); - if (!int_cfg) { - seq_puts(s, "Remote processor config unavailable\n"); - return; - } - - if (pid >= SMP2P_NUM_PROCS || !int_cfg[pid].is_configured) - return; - - msm_smp2p_deinit_rmt_lpb_proc(pid); - smp2p_ut_remote_spinlock_core(s, pid, use_trylock); - msm_smp2p_init_rmt_lpb_proc(pid); -} - -/** - * smp2p_ut_remote_spinlock - Verify remote spinlock for all processors. - * - * @s: pointer to output file - */ -static void smp2p_ut_remote_spinlock(struct seq_file *s) -{ - int pid; - - for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) - smp2p_ut_remote_spinlock_pid(s, pid, false); -} - -/** - * smp2p_ut_remote_spin_trylock - Verify remote trylock for all processors. - * - * @s: Pointer to output file - */ -static void smp2p_ut_remote_spin_trylock(struct seq_file *s) -{ - int pid; - - for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) - smp2p_ut_remote_spinlock_pid(s, pid, true); -} - -/** - * smp2p_ut_remote_spinlock - Verify remote spinlock for all processors. - * - * @s: pointer to output file - * - * This test verifies inbound and outbound functionality for all - * configured remote processor. - */ -static void smp2p_ut_remote_spinlock_modem(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_MODEM_PROC, false); -} - -static void smp2p_ut_remote_spinlock_adsp(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_AUDIO_PROC, false); -} - -static void smp2p_ut_remote_spinlock_dsps(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_SENSOR_PROC, false); -} - -static void smp2p_ut_remote_spinlock_wcnss(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_WIRELESS_PROC, false); -} - -static void smp2p_ut_remote_spinlock_cdsp(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_CDSP_PROC, false); -} - -static void smp2p_ut_remote_spinlock_tz(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_TZ_PROC, false); -} - -/** - * smp2p_ut_remote_spinlock_rpm - Verify remote spinlock. - * - * @s: pointer to output file - * @remote_pid: Remote processor to test - */ -static void smp2p_ut_remote_spinlock_rpm(struct seq_file *s) -{ - int failed = 0; - unsigned long flags; - unsigned n; - unsigned test_num; - struct rpm_spinlock_test *data_ptr; - remote_spinlock_t *smem_spinlock; - bool have_lock; - - seq_printf(s, "Running %s for Apps<->RPM Test\n", - __func__); - do { - smem_spinlock = smem_get_remote_spinlock(); - UT_ASSERT_PTR(smem_spinlock, !=, NULL); - - data_ptr = smem_alloc(SMEM_ID_VENDOR0, - sizeof(struct rpm_spinlock_test), 0, - SMEM_ANY_HOST_FLAG); - UT_ASSERT_PTR(0, !=, data_ptr); - - /* Send start */ - writel_relaxed(0, &data_ptr->apps_lock_count); - writel_relaxed(RPM_CMD_START, &data_ptr->apps_cmd); - - seq_puts(s, "\tWaiting for RPM to start test\n"); - for (n = 0; n < 1000; ++n) { - if (readl_relaxed(&data_ptr->rpm_cmd) != - RPM_CMD_INVALID) - break; - usleep_range(1000, 1200); - } - if (readl_relaxed(&data_ptr->rpm_cmd) == RPM_CMD_INVALID) { - /* timeout waiting for RPM */ - writel_relaxed(RPM_CMD_INVALID, &data_ptr->apps_cmd); - UT_ASSERT_INT(RPM_CMD_LOCKED, !=, RPM_CMD_INVALID); - } - - /* Run spinlock test */ - flags = 0; - have_lock = false; - for (test_num = 0; !failed && test_num < 10000; ++test_num) { - /* acquire spinlock */ - remote_spin_lock_irqsave(smem_spinlock, flags); - have_lock = true; - data_ptr->apps_lock_count++; - writel_relaxed(data_ptr->apps_lock_count, - &data_ptr->apps_lock_count); - writel_relaxed(RPM_CMD_LOCKED, &data_ptr->apps_cmd); - /* - * Ensure that the remote side sees our lock has - * been acquired before we start polling their status. - */ - wmb(); - - /* verify the other side doesn't say it has the lock */ - for (n = 0; n < 1000; ++n) { - UT_ASSERT_HEX(RPM_CMD_UNLOCKED, ==, - readl_relaxed(&data_ptr->rpm_cmd)); - } - if (failed) - break; - - /* release spinlock */ - have_lock = false; - writel_relaxed(RPM_CMD_UNLOCKED, &data_ptr->apps_cmd); - /* - * Ensure that our status-update write was committed - * before we unlock the spinlock. - */ - wmb(); - remote_spin_unlock_irqrestore(smem_spinlock, flags); - } - if (have_lock) - remote_spin_unlock_irqrestore(smem_spinlock, flags); - - /* End test */ - writel_relaxed(RPM_CMD_INVALID, &data_ptr->apps_cmd); - seq_printf(s, "\tLocked spinlock local %u remote %u\n", - readl_relaxed(&data_ptr->apps_lock_count), - readl_relaxed(&data_ptr->rpm_lock_count)); - - if (!failed) - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -struct rmt_spinlock_work_item { - struct work_struct work; - struct completion try_lock; - struct completion locked; - bool has_locked; -}; - -static void ut_remote_spinlock_ssr_worker(struct work_struct *work) -{ - remote_spinlock_t *smem_spinlock; - unsigned long flags; - struct rmt_spinlock_work_item *work_item = - container_of(work, struct rmt_spinlock_work_item, work); - - work_item->has_locked = false; - complete(&work_item->try_lock); - smem_spinlock = smem_get_remote_spinlock(); - if (!smem_spinlock) { - pr_err("%s Failed\n", __func__); - return; - } - - remote_spin_lock_irqsave(smem_spinlock, flags); - remote_spin_unlock_irqrestore(smem_spinlock, flags); - work_item->has_locked = true; - complete(&work_item->locked); -} - -/** - * smp2p_ut_remote_spinlock_ssr - Verify remote spinlock. - * - * @s: pointer to output file - */ -static void smp2p_ut_remote_spinlock_ssr(struct seq_file *s) -{ - int failed = 0; - unsigned long flags; - remote_spinlock_t *smem_spinlock; - int spinlock_owner = 0; - - struct workqueue_struct *ws = NULL; - struct rmt_spinlock_work_item work_item = { .has_locked = false }; - - seq_printf(s, " Running %s Test\n", - __func__); - do { - smem_spinlock = smem_get_remote_spinlock(); - UT_ASSERT_PTR(smem_spinlock, !=, NULL); - - ws = create_singlethread_workqueue("ut_remote_spinlock_ssr"); - UT_ASSERT_PTR(ws, !=, NULL); - INIT_WORK(&work_item.work, ut_remote_spinlock_ssr_worker); - init_completion(&work_item.try_lock); - init_completion(&work_item.locked); - - remote_spin_lock_irqsave(smem_spinlock, flags); - /* Unlock local spin lock and hold HW spinlock */ - spin_unlock_irqrestore(&((smem_spinlock)->local), flags); - - queue_work(ws, &work_item.work); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &work_item.try_lock, HZ * 2), >, 0); - UT_ASSERT_INT((int)work_item.has_locked, ==, 0); - spinlock_owner = remote_spin_owner(smem_spinlock); - UT_ASSERT_INT(spinlock_owner, ==, SMEM_APPS); - remote_spin_release_all(SMEM_APPS); - - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &work_item.locked, HZ * 2), >, 0); - - if (!failed) - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -/** - * smp2p_ut_remote_spinlock_track_core - Verify remote spinlock. - * - * @s: Pointer to output file - * @remote_pid: Remote processor to test - * - * This test has the remote subsystem grab the lock, and then has the local - * subsystem attempt to grab the lock using the trylock() API. It then verifies - * that the ID in the hw_spinlocks array matches the owner of the lock. - */ -static void smp2p_ut_remote_spinlock_track_core(struct seq_file *s, - int remote_pid) -{ - int failed = 0; - struct msm_smp2p_out *handle = NULL; - int ret; - uint32_t test_request; - uint32_t test_response; - struct mock_cb_data cb_out; - struct mock_cb_data cb_in; - unsigned long flags; - int stored_value; - remote_spinlock_t *smem_spinlock; - - seq_printf(s, "Running %s for '%s' remote pid %d\n", - __func__, smp2p_pid_to_name(remote_pid), remote_pid); - - cb_out.initialized = false; - cb_in.initialized = false; - mock_cb_data_init(&cb_out); - mock_cb_data_init(&cb_in); - do { - smem_spinlock = smem_get_remote_spinlock(); - UT_ASSERT_PTR(smem_spinlock, !=, NULL); - - /* Open output entry */ - ret = msm_smp2p_out_open(remote_pid, SMP2P_RLPB_ENTRY_NAME, - &cb_out.nb, &handle); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_out.cb_completion, HZ * 2), - >, 0); - UT_ASSERT_INT(cb_out.cb_count, ==, 1); - UT_ASSERT_INT(cb_out.event_open, ==, 1); - - /* Open inbound entry */ - ret = msm_smp2p_in_register(remote_pid, SMP2P_RLPB_ENTRY_NAME, - &cb_in.nb); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ * 2), - >, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 1); - UT_ASSERT_INT(cb_in.event_open, ==, 1); - - /* Send start */ - mock_cb_data_reset(&cb_in); - mock_cb_data_reset(&cb_out); - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE_REQ(test_request); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_START); - SMP2P_SET_RMT_DATA(test_request, 0x0); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_INT(ret, ==, 0); - - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ * 2), - >, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 1); - UT_ASSERT_INT(cb_in.event_entry_update, ==, 1); - ret = msm_smp2p_in_read(remote_pid, SMP2P_RLPB_ENTRY_NAME, - &test_response); - UT_ASSERT_INT(ret, ==, 0); - - test_response = SMP2P_GET_RMT_CMD(test_response); - if (test_response != SMP2P_LB_CMD_RSPIN_LOCKED && - test_response != SMP2P_LB_CMD_RSPIN_UNLOCKED) { - /* invalid response from remote - abort test */ - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, 0x0); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_HEX(SMP2P_LB_CMD_RSPIN_LOCKED, ==, - test_response); - } - - /* Run spinlock test */ - flags = 0; - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE_REQ(test_request); - - /* try to acquire spinlock */ - remote_spin_trylock_irqsave(smem_spinlock, flags); - /* - * Need to check against the locking token (PID + 1) - * because the remote_spin_owner() API only returns the - * PID. - */ - stored_value = remote_spin_get_hw_spinlocks_element( - smem_spinlock); - UT_ASSERT_INT(stored_value, ==, - remote_spin_owner(smem_spinlock) + 1); - UT_ASSERT_INT(stored_value, ==, remote_pid + 1); - - /* End test */ - test_request = 0x0; - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, 0x0); - (void)msm_smp2p_out_write(handle, test_request); - - /* Cleanup */ - ret = msm_smp2p_out_close(&handle); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_PTR(handle, ==, NULL); - ret = msm_smp2p_in_unregister(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &cb_in.nb); - UT_ASSERT_INT(ret, ==, 0); - - if (!failed) - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - if (handle) { - /* send end command */ - test_request = 0x0; - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, 0x0); - (void)msm_smp2p_out_write(handle, test_request); - (void)msm_smp2p_out_close(&handle); - } - (void)msm_smp2p_in_unregister(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &cb_in.nb); - - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -/** - * smp2p_ut_remote_spinlock_track - Verify PID tracking for modem. - * - * @s: Pointer to output file - * @pid: The processor to test - */ -static void smp2p_ut_remote_spinlock_track(struct seq_file *s, int pid) -{ - struct smp2p_interrupt_config *int_cfg; - - int_cfg = smp2p_get_interrupt_config(); - if (!int_cfg) { - seq_puts(s, "Remote processor config unavailable\n"); - return; - } - - if (pid >= SMP2P_NUM_PROCS || !int_cfg[pid].is_configured) - return; - - msm_smp2p_deinit_rmt_lpb_proc(pid); - smp2p_ut_remote_spinlock_track_core(s, pid); - msm_smp2p_init_rmt_lpb_proc(pid); -} - -/** - * smp2p_ut_remote_spinlock_track - Verify PID tracking for all processors. - * - * @s: Pointer to output file - * - * This test verifies PID tracking for all configured remote processors. - */ -static void smp2p_ut_remote_spinlock_track_modem(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_MODEM_PROC); -} - -static void smp2p_ut_remote_spinlock_track_adsp(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_AUDIO_PROC); -} - -static void smp2p_ut_remote_spinlock_track_dsps(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_SENSOR_PROC); -} - -static void smp2p_ut_remote_spinlock_track_wcnss(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_WIRELESS_PROC); -} - -static void smp2p_ut_remote_spinlock_track_cdsp(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_CDSP_PROC); -} - -static void smp2p_ut_remote_spinlock_track_tz(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_TZ_PROC); -} - -static int __init smp2p_debugfs_init(void) -{ - /* - * Add Unit Test entries. - * - * The idea with unit tests is that you can run all of them - * from ADB shell by doing: - * adb shell - * cat ut* - * - * And if particular tests fail, you can then repeatedly run the - * failing tests as you debug and resolve the failing test. - */ - smp2p_debug_create("ut_remote_spinlock", - smp2p_ut_remote_spinlock); - smp2p_debug_create("ut_remote_spin_trylock", - smp2p_ut_remote_spin_trylock); - smp2p_debug_create("ut_remote_spinlock_modem", - smp2p_ut_remote_spinlock_modem); - smp2p_debug_create("ut_remote_spinlock_adsp", - smp2p_ut_remote_spinlock_adsp); - smp2p_debug_create("ut_remote_spinlock_dsps", - smp2p_ut_remote_spinlock_dsps); - smp2p_debug_create("ut_remote_spinlock_wcnss", - smp2p_ut_remote_spinlock_wcnss); - smp2p_debug_create("ut_remote_spinlock_cdsp", - smp2p_ut_remote_spinlock_cdsp); - smp2p_debug_create("ut_remote_spinlock_tz", - smp2p_ut_remote_spinlock_tz); - smp2p_debug_create("ut_remote_spinlock_rpm", - smp2p_ut_remote_spinlock_rpm); - smp2p_debug_create_u32("ut_remote_spinlock_time", - &ut_remote_spinlock_run_time); - smp2p_debug_create("ut_remote_spinlock_ssr", - &smp2p_ut_remote_spinlock_ssr); - smp2p_debug_create("ut_remote_spinlock_track_modem", - &smp2p_ut_remote_spinlock_track_modem); - smp2p_debug_create("ut_remote_spinlock_track_adsp", - &smp2p_ut_remote_spinlock_track_adsp); - smp2p_debug_create("ut_remote_spinlock_track_dsps", - &smp2p_ut_remote_spinlock_track_dsps); - smp2p_debug_create("ut_remote_spinlock_track_wcnss", - &smp2p_ut_remote_spinlock_track_wcnss); - smp2p_debug_create("ut_remote_spinlock_track_cdsp", - &smp2p_ut_remote_spinlock_track_cdsp); - smp2p_debug_create("ut_remote_spinlock_track_tz", - &smp2p_ut_remote_spinlock_track_tz); - return 0; -} -module_init(smp2p_debugfs_init); diff --git a/drivers/soc/qcom/smp2p_test.c b/drivers/soc/qcom/smp2p_test.c deleted file mode 100644 index e81bada0137a..000000000000 --- a/drivers/soc/qcom/smp2p_test.c +++ /dev/null @@ -1,1327 +0,0 @@ -/* drivers/soc/qcom/smp2p_test.c - * - * 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 - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "smp2p_private.h" -#include "smp2p_test_common.h" - -/** - * smp2p_ut_local_basic - Basic sanity test using local loopback. - * - * @s: pointer to output file - * - * This test simulates a simple write and read - * when remote processor does not exist. - */ -static void smp2p_ut_local_basic(struct seq_file *s) -{ - int failed = 0; - struct msm_smp2p_out *smp2p_obj; - struct msm_smp2p_remote_mock *rmp = NULL; - int ret; - uint32_t test_request; - uint32_t test_response = 0; - static struct mock_cb_data cb_data; - - seq_printf(s, "Running %s\n", __func__); - mock_cb_data_init(&cb_data); - do { - /* initialize mock edge and start opening */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - rmp = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(rmp, !=, NULL); - - rmp->rx_interrupt_count = 0; - memset(&rmp->remote_item, 0, - sizeof(struct smp2p_smem_item)); - - msm_smp2p_set_remote_mock_exists(false); - - ret = msm_smp2p_out_open(SMP2P_REMOTE_MOCK_PROC, "smp2p", - &cb_data.nb, &smp2p_obj); - UT_ASSERT_INT(ret, ==, 0); - - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - UT_ASSERT_INT(cb_data.cb_count, ==, 0); - rmp->rx_interrupt_count = 0; - - /* simulate response from remote side */ - rmp->remote_item.header.magic = SMP2P_MAGIC; - SMP2P_SET_LOCAL_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_REMOTE_MOCK_PROC); - SMP2P_SET_REMOTE_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_APPS_PROC); - SMP2P_SET_VERSION( - rmp->remote_item.header.feature_version, 1); - SMP2P_SET_FEATURES( - rmp->remote_item.header.feature_version, 0); - SMP2P_SET_ENT_TOTAL( - rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY); - SMP2P_SET_ENT_VALID( - rmp->remote_item.header.valid_total_ent, 0); - rmp->remote_item.header.flags = 0x0; - msm_smp2p_set_remote_mock_exists(true); - rmp->tx_interrupt(); - - /* verify port was opened */ - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_data.cb_completion, HZ / 2), >, 0); - UT_ASSERT_INT(cb_data.cb_count, ==, 1); - UT_ASSERT_INT(cb_data.event_open, ==, 1); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 2); - - /* do write (test outbound entries) */ - rmp->rx_interrupt_count = 0; - test_request = 0xC0DE; - ret = msm_smp2p_out_write(smp2p_obj, test_request); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - - /* do read (test inbound entries) */ - ret = msm_smp2p_out_read(smp2p_obj, &test_response); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(test_request, ==, test_response); - - ret = msm_smp2p_out_close(&smp2p_obj); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_PTR(smp2p_obj, ==, 0); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - (void)msm_smp2p_out_close(&smp2p_obj); - } -} - -/** - * smp2p_ut_local_late_open - Verify post-negotiation opening. - * - * @s: pointer to output file - * - * Verify entry creation for opening entries after negotiation is complete. - */ -static void smp2p_ut_local_late_open(struct seq_file *s) -{ - int failed = 0; - struct msm_smp2p_out *smp2p_obj; - struct msm_smp2p_remote_mock *rmp = NULL; - int ret; - uint32_t test_request; - uint32_t test_response = 0; - static struct mock_cb_data cb_data; - - seq_printf(s, "Running %s\n", __func__); - mock_cb_data_init(&cb_data); - do { - /* initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - rmp = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(rmp, !=, NULL); - - rmp->rx_interrupt_count = 0; - memset(&rmp->remote_item, 0, - sizeof(struct smp2p_smem_item)); - rmp->remote_item.header.magic = SMP2P_MAGIC; - SMP2P_SET_LOCAL_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_REMOTE_MOCK_PROC); - SMP2P_SET_REMOTE_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_APPS_PROC); - SMP2P_SET_VERSION( - rmp->remote_item.header.feature_version, 1); - SMP2P_SET_FEATURES( - rmp->remote_item.header.feature_version, 0); - SMP2P_SET_ENT_TOTAL( - rmp->remote_item.header.valid_total_ent, - SMP2P_MAX_ENTRY); - SMP2P_SET_ENT_VALID( - rmp->remote_item.header.valid_total_ent, 0); - rmp->remote_item.header.flags = 0x0; - - msm_smp2p_set_remote_mock_exists(true); - - ret = msm_smp2p_out_open(SMP2P_REMOTE_MOCK_PROC, "smp2p", - &cb_data.nb, &smp2p_obj); - UT_ASSERT_INT(ret, ==, 0); - - /* verify port was opened */ - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_data.cb_completion, HZ / 2), - >, 0); - UT_ASSERT_INT(cb_data.cb_count, ==, 1); - UT_ASSERT_INT(cb_data.event_open, ==, 1); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 2); - - /* do write (test outbound entries) */ - rmp->rx_interrupt_count = 0; - test_request = 0xC0DE; - ret = msm_smp2p_out_write(smp2p_obj, test_request); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - - /* do read (test inbound entries) */ - ret = msm_smp2p_out_read(smp2p_obj, &test_response); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(test_request, ==, test_response); - - ret = msm_smp2p_out_close(&smp2p_obj); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_PTR(smp2p_obj, ==, 0); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - (void)msm_smp2p_out_close(&smp2p_obj); - } -} - -/** - * smp2p_ut_local_early_open - Verify pre-negotiation opening. - * - * @s: pointer to output file - * - * Verify entry creation for opening entries before negotiation is complete. - */ -static void smp2p_ut_local_early_open(struct seq_file *s) -{ - int failed = 0; - struct msm_smp2p_out *smp2p_obj; - struct msm_smp2p_remote_mock *rmp = NULL; - struct smp2p_smem *outbound_item; - int negotiation_state; - int ret; - uint32_t test_request; - uint32_t test_response = 0; - static struct mock_cb_data cb_data; - - seq_printf(s, "Running %s\n", __func__); - mock_cb_data_init(&cb_data); - do { - /* initialize mock edge, but don't enable, yet */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - rmp = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(rmp, !=, NULL); - - rmp->rx_interrupt_count = 0; - memset(&rmp->remote_item, 0, - sizeof(struct smp2p_smem_item)); - rmp->remote_item.header.magic = SMP2P_MAGIC; - SMP2P_SET_LOCAL_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_REMOTE_MOCK_PROC); - SMP2P_SET_REMOTE_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_APPS_PROC); - SMP2P_SET_VERSION( - rmp->remote_item.header.feature_version, 1); - SMP2P_SET_FEATURES( - rmp->remote_item.header.feature_version, 0); - SMP2P_SET_ENT_TOTAL( - rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY); - SMP2P_SET_ENT_VALID( - rmp->remote_item.header.valid_total_ent, 0); - rmp->remote_item.header.flags = 0x0; - - msm_smp2p_set_remote_mock_exists(false); - UT_ASSERT_PTR(NULL, ==, - smp2p_get_in_item(SMP2P_REMOTE_MOCK_PROC)); - - /* initiate open, but verify it doesn't complete */ - ret = msm_smp2p_out_open(SMP2P_REMOTE_MOCK_PROC, "smp2p", - &cb_data.nb, &smp2p_obj); - UT_ASSERT_INT(ret, ==, 0); - - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_data.cb_completion, HZ / 8), - ==, 0); - UT_ASSERT_INT(cb_data.cb_count, ==, 0); - UT_ASSERT_INT(cb_data.event_open, ==, 0); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - - outbound_item = smp2p_get_out_item(SMP2P_REMOTE_MOCK_PROC, - &negotiation_state); - UT_ASSERT_PTR(outbound_item, !=, NULL); - UT_ASSERT_INT(negotiation_state, ==, SMP2P_EDGE_STATE_OPENING); - UT_ASSERT_INT(0, ==, - SMP2P_GET_ENT_VALID(outbound_item->valid_total_ent)); - - /* verify that read/write don't work yet */ - rmp->rx_interrupt_count = 0; - test_request = 0x0; - ret = msm_smp2p_out_write(smp2p_obj, test_request); - UT_ASSERT_INT(ret, ==, -ENODEV); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 0); - - ret = msm_smp2p_out_read(smp2p_obj, &test_response); - UT_ASSERT_INT(ret, ==, -ENODEV); - - /* allocate remote entry and verify open */ - msm_smp2p_set_remote_mock_exists(true); - rmp->tx_interrupt(); - - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_data.cb_completion, HZ / 2), - >, 0); - UT_ASSERT_INT(cb_data.cb_count, ==, 1); - UT_ASSERT_INT(cb_data.event_open, ==, 1); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 2); - - /* do write (test outbound entries) */ - rmp->rx_interrupt_count = 0; - test_request = 0xC0DE; - ret = msm_smp2p_out_write(smp2p_obj, test_request); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - - /* do read (test inbound entries) */ - ret = msm_smp2p_out_read(smp2p_obj, &test_response); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(test_request, ==, test_response); - - ret = msm_smp2p_out_close(&smp2p_obj); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_PTR(smp2p_obj, ==, 0); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - (void)msm_smp2p_out_close(&smp2p_obj); - } -} - -/** - * smp2p_ut_mock_loopback - Exercise the remote loopback using remote mock. - * - * @s: pointer to output file - * - * This test exercises the remote loopback code using - * remote mock object. The remote mock object simulates the remote - * processor sending remote loopback commands to the local processor. - */ -static void smp2p_ut_mock_loopback(struct seq_file *s) -{ - int failed = 0; - struct msm_smp2p_remote_mock *rmp = NULL; - int ret; - uint32_t test_request = 0; - uint32_t test_response = 0; - struct msm_smp2p_out *local; - - seq_printf(s, "Running %s\n", __func__); - do { - /* Initialize the mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - rmp = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(rmp, !=, NULL); - - memset(&rmp->remote_item, 0, - sizeof(struct smp2p_smem_item)); - rmp->remote_item.header.magic = SMP2P_MAGIC; - SMP2P_SET_LOCAL_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_REMOTE_MOCK_PROC); - SMP2P_SET_REMOTE_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_APPS_PROC); - SMP2P_SET_VERSION( - rmp->remote_item.header.feature_version, 1); - SMP2P_SET_FEATURES( - rmp->remote_item.header.feature_version, 0); - SMP2P_SET_ENT_TOTAL( - rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY); - SMP2P_SET_ENT_VALID( - rmp->remote_item.header.valid_total_ent, 1); - rmp->remote_item.header.flags = 0x0; - msm_smp2p_set_remote_mock_exists(true); - - /* Create test entry and attach loopback server */ - rmp->rx_interrupt_count = 0; - reinit_completion(&rmp->cb_completion); - strlcpy(rmp->remote_item.entries[0].name, "smp2p", - SMP2P_MAX_ENTRY_NAME); - rmp->remote_item.entries[0].entry = 0; - rmp->tx_interrupt(); - - local = msm_smp2p_init_rmt_lpb_proc(SMP2P_REMOTE_MOCK_PROC); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &rmp->cb_completion, HZ / 2), - >, 0); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 2); - - /* Send Echo Command */ - rmp->rx_interrupt_count = 0; - reinit_completion(&rmp->cb_completion); - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_ECHO); - SMP2P_SET_RMT_DATA(test_request, 10); - rmp->remote_item.entries[0].entry = test_request; - rmp->tx_interrupt(); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &rmp->cb_completion, HZ / 2), - >, 0); - - /* Verify Echo Response */ - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - ret = msm_smp2p_out_read(local, - &test_response); - UT_ASSERT_INT(ret, ==, 0); - test_response = SMP2P_GET_RMT_DATA(test_response); - UT_ASSERT_INT(test_response, ==, 10); - - /* Send PINGPONG command */ - test_request = 0; - test_response = 0; - rmp->rx_interrupt_count = 0; - reinit_completion(&rmp->cb_completion); - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_PINGPONG); - SMP2P_SET_RMT_DATA(test_request, 10); - rmp->remote_item.entries[0].entry = test_request; - rmp->tx_interrupt(); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &rmp->cb_completion, HZ / 2), - >, 0); - - /* Verify PINGPONG Response */ - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - ret = msm_smp2p_out_read(local, &test_response); - UT_ASSERT_INT(ret, ==, 0); - test_response = SMP2P_GET_RMT_DATA(test_response); - UT_ASSERT_INT(test_response, ==, 9); - - /* Send CLEARALL command */ - test_request = 0; - test_response = 0; - rmp->rx_interrupt_count = 0; - reinit_completion(&rmp->cb_completion); - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_CLEARALL); - SMP2P_SET_RMT_DATA(test_request, 10); - rmp->remote_item.entries[0].entry = test_request; - rmp->tx_interrupt(); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &rmp->cb_completion, HZ / 2), - >, 0); - - /* Verify CLEARALL response */ - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - ret = msm_smp2p_out_read(local, &test_response); - UT_ASSERT_INT(ret, ==, 0); - test_response = SMP2P_GET_RMT_DATA(test_response); - UT_ASSERT_INT(test_response, ==, 0); - - ret = msm_smp2p_deinit_rmt_lpb_proc(SMP2P_REMOTE_MOCK_PROC); - UT_ASSERT_INT(ret, ==, 0); - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - msm_smp2p_deinit_rmt_lpb_proc(SMP2P_REMOTE_MOCK_PROC); - } -} - -/** - * smp2p_ut_remote_inout_core - Verify inbound/outbound functionality. - * - * @s: pointer to output file - * @remote_pid: Remote processor to test - * - * This test verifies inbound/outbound functionality for the remote processor. - */ -static void smp2p_ut_remote_inout_core(struct seq_file *s, int remote_pid) -{ - int failed = 0; - struct msm_smp2p_out *handle; - int ret; - uint32_t test_request; - uint32_t test_response = 0; - static struct mock_cb_data cb_out; - static struct mock_cb_data cb_in; - - seq_printf(s, "Running %s for '%s' remote pid %d\n", - __func__, smp2p_pid_to_name(remote_pid), remote_pid); - mock_cb_data_init(&cb_out); - mock_cb_data_init(&cb_in); - do { - /* Open output entry */ - ret = msm_smp2p_out_open(remote_pid, "smp2p", - &cb_out.nb, &handle); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_out.cb_completion, HZ / 2), - >, 0); - UT_ASSERT_INT(cb_out.cb_count, ==, 1); - UT_ASSERT_INT(cb_out.event_open, ==, 1); - - /* Open inbound entry */ - ret = msm_smp2p_in_register(remote_pid, "smp2p", - &cb_in.nb); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ / 2), - >, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 1); - UT_ASSERT_INT(cb_in.event_open, ==, 1); - - /* Write an echo request */ - mock_cb_data_reset(&cb_out); - mock_cb_data_reset(&cb_in); - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_ECHO); - SMP2P_SET_RMT_DATA(test_request, 0xAA55); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_INT(ret, ==, 0); - - /* Verify inbound reply */ - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ / 2), - >, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 1); - UT_ASSERT_INT(cb_in.event_entry_update, ==, 1); - UT_ASSERT_INT(SMP2P_GET_RMT_DATA( - cb_in.entry_data.current_value), ==, 0xAA55); - - ret = msm_smp2p_in_read(remote_pid, "smp2p", &test_response); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(0, ==, SMP2P_GET_RMT_CMD_TYPE(test_response)); - UT_ASSERT_INT(SMP2P_LB_CMD_ECHO, ==, - SMP2P_GET_RMT_CMD(test_response)); - UT_ASSERT_INT(0xAA55, ==, SMP2P_GET_RMT_DATA(test_response)); - - /* Write a clear all request */ - mock_cb_data_reset(&cb_in); - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_CLEARALL); - SMP2P_SET_RMT_DATA(test_request, 0xAA55); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_INT(ret, ==, 0); - - /* Verify inbound reply */ - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ / 2), - >, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 1); - UT_ASSERT_INT(cb_in.event_entry_update, ==, 1); - UT_ASSERT_INT(SMP2P_GET_RMT_DATA( - cb_in.entry_data.current_value), ==, 0x0000); - - ret = msm_smp2p_in_read(remote_pid, "smp2p", &test_response); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(0, ==, SMP2P_GET_RMT_CMD_TYPE(test_response)); - UT_ASSERT_INT(0x0000, ==, SMP2P_GET_RMT_DATA(test_response)); - - /* Write a decrement request */ - mock_cb_data_reset(&cb_in); - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_PINGPONG); - SMP2P_SET_RMT_DATA(test_request, 0xAA55); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_INT(ret, ==, 0); - - /* Verify inbound reply */ - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ / 2), - >, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 1); - UT_ASSERT_INT(cb_in.event_entry_update, ==, 1); - UT_ASSERT_INT(SMP2P_GET_RMT_DATA( - cb_in.entry_data.current_value), ==, 0xAA54); - - ret = msm_smp2p_in_read(remote_pid, "smp2p", &test_response); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(0, ==, SMP2P_GET_RMT_CMD_TYPE(test_response)); - UT_ASSERT_INT(SMP2P_LB_CMD_PINGPONG, ==, - SMP2P_GET_RMT_CMD(test_response)); - UT_ASSERT_INT(0xAA54, ==, SMP2P_GET_RMT_DATA(test_response)); - - /* Test the ignore flag */ - mock_cb_data_reset(&cb_in); - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_RLPB_IGNORE); - SMP2P_SET_RMT_DATA(test_request, 0xAA55); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_INT(ret, ==, 0); - - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ / 2), - ==, 0); - UT_ASSERT_INT(cb_in.cb_count, ==, 0); - UT_ASSERT_INT(cb_in.event_entry_update, ==, 0); - ret = msm_smp2p_in_read(remote_pid, "smp2p", &test_response); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT(0xAA54, ==, SMP2P_GET_RMT_DATA(test_response)); - - /* Cleanup */ - ret = msm_smp2p_out_close(&handle); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_PTR(handle, ==, 0); - ret = msm_smp2p_in_unregister(remote_pid, "smp2p", &cb_in.nb); - UT_ASSERT_INT(ret, ==, 0); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - if (handle) - (void)msm_smp2p_out_close(&handle); - (void)msm_smp2p_in_unregister(remote_pid, "smp2p", &cb_in.nb); - - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -/** - * smp2p_ut_remote_inout - Verify inbound/outbound functionality for all. - * - * @s: pointer to output file - * - * This test verifies inbound and outbound functionality for all - * configured remote processor. - */ -static void smp2p_ut_remote_inout(struct seq_file *s) -{ - struct smp2p_interrupt_config *int_cfg; - int pid; - - int_cfg = smp2p_get_interrupt_config(); - if (!int_cfg) { - seq_puts(s, "Remote processor config unavailable\n"); - return; - } - - for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) { - if (!int_cfg[pid].is_configured) - continue; - - msm_smp2p_deinit_rmt_lpb_proc(pid); - smp2p_ut_remote_inout_core(s, pid); - msm_smp2p_init_rmt_lpb_proc(pid); - } -} - -/** - * smp2p_ut_remote_out_max_entries_core - Verify open functionality. - * - * @s: pointer to output file - * @remote_pid: Remote processor for which the test is executed. - * - * This test verifies open functionality by creating maximum outbound entries. - */ -static void smp2p_ut_remote_out_max_entries_core(struct seq_file *s, - int remote_pid) -{ - int j = 0; - int failed = 0; - struct msm_smp2p_out *handle[SMP2P_MAX_ENTRY]; - int ret; - static struct mock_cb_data cb_out[SMP2P_MAX_ENTRY]; - char entry_name[SMP2P_MAX_ENTRY_NAME]; - int num_created; - - seq_printf(s, "Running %s for '%s' remote pid %d\n", - __func__, smp2p_pid_to_name(remote_pid), remote_pid); - - for (j = 0; j < SMP2P_MAX_ENTRY; j++) { - handle[j] = NULL; - mock_cb_data_init(&cb_out[j]); - } - - do { - num_created = 0; - for (j = 0; j < SMP2P_MAX_ENTRY; j++) { - /* Open as many output entries as possible */ - scnprintf((char *)entry_name, SMP2P_MAX_ENTRY_NAME, - "smp2p%d", j); - ret = msm_smp2p_out_open(remote_pid, entry_name, - &cb_out[j].nb, &handle[j]); - if (ret == -ENOMEM) - /* hit max number */ - break; - UT_ASSERT_INT(ret, ==, 0); - ++num_created; - } - if (failed) - break; - - /* verify we created more than 1 entry */ - UT_ASSERT_INT(num_created, <=, SMP2P_MAX_ENTRY); - UT_ASSERT_INT(num_created, >, 0); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } - - /* cleanup */ - for (j = 0; j < SMP2P_MAX_ENTRY; j++) - ret = msm_smp2p_out_close(&handle[j]); -} - -/** - * smp2p_ut_remote_out_max_entries - Verify open for all configured processors. - * - * @s: pointer to output file - * - * This test verifies creating max number of entries for - * all configured remote processor. - */ -static void smp2p_ut_remote_out_max_entries(struct seq_file *s) -{ - struct smp2p_interrupt_config *int_cfg; - int pid; - - int_cfg = smp2p_get_interrupt_config(); - if (!int_cfg) { - seq_puts(s, "Remote processor config unavailable\n"); - return; - } - - for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) { - if (!int_cfg[pid].is_configured) - continue; - - smp2p_ut_remote_out_max_entries_core(s, pid); - } -} - -/** - * smp2p_ut_local_in_max_entries - Verify registering and unregistering. - * - * @s: pointer to output file - * - * This test verifies registering and unregistering for inbound entries using - * the remote mock processor. - */ -static void smp2p_ut_local_in_max_entries(struct seq_file *s) -{ - int j = 0; - int failed = 0; - struct msm_smp2p_remote_mock *rmp = NULL; - int ret; - static struct mock_cb_data cb_in[SMP2P_MAX_ENTRY]; - static struct mock_cb_data cb_out; - - seq_printf(s, "Running %s\n", __func__); - - for (j = 0; j < SMP2P_MAX_ENTRY; j++) - mock_cb_data_init(&cb_in[j]); - - mock_cb_data_init(&cb_out); - - do { - /* Initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - rmp = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(rmp, !=, NULL); - - rmp->rx_interrupt_count = 0; - memset(&rmp->remote_item, 0, - sizeof(struct smp2p_smem_item)); - rmp->remote_item.header.magic = SMP2P_MAGIC; - SMP2P_SET_LOCAL_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_REMOTE_MOCK_PROC); - SMP2P_SET_REMOTE_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_APPS_PROC); - SMP2P_SET_VERSION( - rmp->remote_item.header.feature_version, 1); - SMP2P_SET_FEATURES( - rmp->remote_item.header.feature_version, 0); - SMP2P_SET_ENT_TOTAL( - rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY); - SMP2P_SET_ENT_VALID( - rmp->remote_item.header.valid_total_ent, 0); - rmp->remote_item.header.flags = 0x0; - msm_smp2p_set_remote_mock_exists(true); - - /* Create Max Entries in the remote mock object */ - for (j = 0; j < SMP2P_MAX_ENTRY; j++) { - scnprintf(rmp->remote_item.entries[j].name, - SMP2P_MAX_ENTRY_NAME, "smp2p%d", j); - rmp->remote_item.entries[j].entry = 0; - rmp->tx_interrupt(); - } - - /* Register for in entries */ - for (j = 0; j < SMP2P_MAX_ENTRY; j++) { - ret = msm_smp2p_in_register(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[j].name, - &(cb_in[j].nb)); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &(cb_in[j].cb_completion), HZ / 2), - >, 0); - UT_ASSERT_INT(cb_in[j].cb_count, ==, 1); - UT_ASSERT_INT(cb_in[j].event_entry_update, ==, 0); - } - UT_ASSERT_INT(j, ==, SMP2P_MAX_ENTRY); - - /* Unregister */ - for (j = 0; j < SMP2P_MAX_ENTRY; j++) { - ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[j].name, - &(cb_in[j].nb)); - UT_ASSERT_INT(ret, ==, 0); - } - UT_ASSERT_INT(j, ==, SMP2P_MAX_ENTRY); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - - for (j = 0; j < SMP2P_MAX_ENTRY; j++) - ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[j].name, - &(cb_in[j].nb)); - } -} - -/** - * smp2p_ut_local_in_multiple - Verify Multiple Inbound Registration. - * - * @s: pointer to output file - * - * This test verifies multiple clients registering for same inbound entries - * using the remote mock processor. - */ -static void smp2p_ut_local_in_multiple(struct seq_file *s) -{ - int failed = 0; - struct msm_smp2p_remote_mock *rmp = NULL; - int ret; - static struct mock_cb_data cb_in_1; - static struct mock_cb_data cb_in_2; - static struct mock_cb_data cb_out; - - seq_printf(s, "Running %s\n", __func__); - - mock_cb_data_init(&cb_in_1); - mock_cb_data_init(&cb_in_2); - mock_cb_data_init(&cb_out); - - do { - /* Initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - rmp = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(rmp, !=, NULL); - - rmp->rx_interrupt_count = 0; - memset(&rmp->remote_item, 0, - sizeof(struct smp2p_smem_item)); - rmp->remote_item.header.magic = SMP2P_MAGIC; - SMP2P_SET_LOCAL_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_REMOTE_MOCK_PROC); - SMP2P_SET_REMOTE_PID( - rmp->remote_item.header.rem_loc_proc_id, - SMP2P_APPS_PROC); - SMP2P_SET_VERSION( - rmp->remote_item.header.feature_version, 1); - SMP2P_SET_FEATURES( - rmp->remote_item.header.feature_version, 0); - SMP2P_SET_ENT_TOTAL( - rmp->remote_item.header.valid_total_ent, 1); - SMP2P_SET_ENT_VALID( - rmp->remote_item.header.valid_total_ent, 0); - rmp->remote_item.header.flags = 0x0; - msm_smp2p_set_remote_mock_exists(true); - - /* Create an Entry in the remote mock object */ - scnprintf(rmp->remote_item.entries[0].name, - SMP2P_MAX_ENTRY_NAME, "smp2p%d", 1); - rmp->remote_item.entries[0].entry = 0; - rmp->tx_interrupt(); - - /* Register multiple clients for the inbound entry */ - ret = msm_smp2p_in_register(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[0].name, - &cb_in_1.nb); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &(cb_in_1.cb_completion), HZ / 2), - >, 0); - UT_ASSERT_INT(cb_in_1.cb_count, ==, 1); - UT_ASSERT_INT(cb_in_1.event_entry_update, ==, 0); - - ret = msm_smp2p_in_register(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[0].name, - &cb_in_2.nb); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &(cb_in_2.cb_completion), HZ / 2), - >, 0); - UT_ASSERT_INT(cb_in_2.cb_count, ==, 1); - UT_ASSERT_INT(cb_in_2.event_entry_update, ==, 0); - - - /* Unregister the clients */ - ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[0].name, - &(cb_in_1.nb)); - UT_ASSERT_INT(ret, ==, 0); - - ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[0].name, - &(cb_in_2.nb)); - UT_ASSERT_INT(ret, ==, 0); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - - ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[0].name, - &(cb_in_1.nb)); - - ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, - rmp->remote_item.entries[0].name, - &(cb_in_2.nb)); - } -} - -/** - * smp2p_ut_local_ssr_ack - Verify SSR Done/ACK Feature - * - * @s: pointer to output file - */ -static void smp2p_ut_local_ssr_ack(struct seq_file *s) -{ - int failed = 0; - struct msm_smp2p_remote_mock *rmp = NULL; - int ret; - - seq_printf(s, "Running %s\n", __func__); - do { - struct smp2p_smem *rhdr; - struct smp2p_smem *lhdr; - int negotiation_state; - - /* initialize v1 without SMP2P_FEATURE_SSR_ACK enabled */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - rmp = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(rmp, !=, NULL); - rhdr = &rmp->remote_item.header; - - rmp->rx_interrupt_count = 0; - memset(&rmp->remote_item, 0, sizeof(struct smp2p_smem_item)); - rhdr->magic = SMP2P_MAGIC; - SMP2P_SET_LOCAL_PID(rhdr->rem_loc_proc_id, - SMP2P_REMOTE_MOCK_PROC); - SMP2P_SET_REMOTE_PID(rhdr->rem_loc_proc_id, SMP2P_APPS_PROC); - SMP2P_SET_VERSION(rhdr->feature_version, 1); - SMP2P_SET_FEATURES(rhdr->feature_version, 0); - SMP2P_SET_ENT_TOTAL(rhdr->valid_total_ent, SMP2P_MAX_ENTRY); - SMP2P_SET_ENT_VALID(rhdr->valid_total_ent, 0); - rhdr->flags = 0x0; - msm_smp2p_set_remote_mock_exists(true); - rmp->tx_interrupt(); - - /* verify edge is open */ - lhdr = smp2p_get_out_item(SMP2P_REMOTE_MOCK_PROC, - &negotiation_state); - UT_ASSERT_PTR(NULL, !=, lhdr); - UT_ASSERT_INT(negotiation_state, ==, SMP2P_EDGE_STATE_OPENED); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - - /* verify no response to ack feature */ - rmp->rx_interrupt_count = 0; - SMP2P_SET_RESTART_DONE(rhdr->flags, 1); - rmp->tx_interrupt(); - UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_DONE(lhdr->flags)); - UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_ACK(lhdr->flags)); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 0); - - /* initialize v1 with SMP2P_FEATURE_SSR_ACK enabled */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - rmp = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(rmp, !=, NULL); - rhdr = &rmp->remote_item.header; - - rmp->rx_interrupt_count = 0; - memset(&rmp->remote_item, 0, sizeof(struct smp2p_smem_item)); - rhdr->magic = SMP2P_MAGIC; - SMP2P_SET_LOCAL_PID(rhdr->rem_loc_proc_id, - SMP2P_REMOTE_MOCK_PROC); - SMP2P_SET_REMOTE_PID(rhdr->rem_loc_proc_id, SMP2P_APPS_PROC); - SMP2P_SET_VERSION(rhdr->feature_version, 1); - SMP2P_SET_FEATURES(rhdr->feature_version, - SMP2P_FEATURE_SSR_ACK); - SMP2P_SET_ENT_TOTAL(rhdr->valid_total_ent, SMP2P_MAX_ENTRY); - SMP2P_SET_ENT_VALID(rhdr->valid_total_ent, 0); - rmp->rx_interrupt_count = 0; - rhdr->flags = 0x0; - msm_smp2p_set_remote_mock_exists(true); - rmp->tx_interrupt(); - - /* verify edge is open */ - lhdr = smp2p_get_out_item(SMP2P_REMOTE_MOCK_PROC, - &negotiation_state); - UT_ASSERT_PTR(NULL, !=, lhdr); - UT_ASSERT_INT(negotiation_state, ==, SMP2P_EDGE_STATE_OPENED); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - - /* verify response to ack feature */ - rmp->rx_interrupt_count = 0; - SMP2P_SET_RESTART_DONE(rhdr->flags, 1); - rmp->tx_interrupt(); - UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_DONE(lhdr->flags)); - UT_ASSERT_INT(1, ==, SMP2P_GET_RESTART_ACK(lhdr->flags)); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - - rmp->rx_interrupt_count = 0; - SMP2P_SET_RESTART_DONE(rhdr->flags, 0); - rmp->tx_interrupt(); - UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_DONE(lhdr->flags)); - UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_ACK(lhdr->flags)); - UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -/** - * get_ssr_name_for_proc - Retrieve an SSR name from the provided list - * - * @names: List of possible processor names - * @name_len: The length of @names - * @index: Index into @names - * - * Return: Pointer to the next processor name, NULL in error conditions - */ -static char *get_ssr_name_for_proc(char *names[], size_t name_len, int index) -{ - if (index >= name_len) { - pr_err("%s: SSR failed; check subsys name table\n", - __func__); - return NULL; - } - - return names[index]; -} - -/** - * smp2p_ut_local_ssr_ack - Verify SSR Done/ACK Feature - * - * @s: pointer to output file - * @rpid: Remote processor ID - * @int_cfg: Interrupt config - */ -static void smp2p_ut_remotesubsys_ssr_ack(struct seq_file *s, uint32_t rpid, - struct smp2p_interrupt_config *int_cfg) -{ - int failed = 0; - - seq_printf(s, "Running %s\n", __func__); - do { - struct smp2p_smem *rhdr; - struct smp2p_smem *lhdr; - int negotiation_state; - int name_index; - int ret; - uint32_t ssr_done_start; - bool ssr_ack_enabled = false; - bool ssr_success = false; - char *name = NULL; - - static char *mpss_names[] = {"modem", "mpss"}; - static char *lpass_names[] = {"adsp", "lpass"}; - static char *sensor_names[] = {"slpi", "dsps"}; - static char *wcnss_names[] = {"wcnss"}; - - lhdr = smp2p_get_out_item(rpid, &negotiation_state); - UT_ASSERT_PTR(NULL, !=, lhdr); - UT_ASSERT_INT(SMP2P_EDGE_STATE_OPENED, ==, negotiation_state); - - rhdr = smp2p_get_in_item(rpid); - UT_ASSERT_PTR(NULL, !=, rhdr); - - /* get initial state of SSR flags */ - if (SMP2P_GET_FEATURES(rhdr->feature_version) - & SMP2P_FEATURE_SSR_ACK) - ssr_ack_enabled = true; - else - ssr_ack_enabled = false; - - ssr_done_start = SMP2P_GET_RESTART_DONE(rhdr->flags); - UT_ASSERT_INT(ssr_done_start, ==, - SMP2P_GET_RESTART_ACK(lhdr->flags)); - - /* trigger restart */ - name_index = 0; - while (!ssr_success) { - - switch (rpid) { - case SMP2P_MODEM_PROC: - name = get_ssr_name_for_proc(mpss_names, - ARRAY_SIZE(mpss_names), - name_index); - break; - case SMP2P_AUDIO_PROC: - name = get_ssr_name_for_proc(lpass_names, - ARRAY_SIZE(lpass_names), - name_index); - break; - case SMP2P_SENSOR_PROC: - name = get_ssr_name_for_proc(sensor_names, - ARRAY_SIZE(sensor_names), - name_index); - break; - case SMP2P_WIRELESS_PROC: - name = get_ssr_name_for_proc(wcnss_names, - ARRAY_SIZE(wcnss_names), - name_index); - break; - default: - pr_err("%s: Invalid proc ID %d given for ssr\n", - __func__, rpid); - } - - if (!name) { - seq_puts(s, "\tSSR failed; check subsys name table\n"); - failed = true; - break; - } - - seq_printf(s, "Restarting '%s'\n", name); - ret = subsystem_restart(name); - if (ret == -ENODEV) { - seq_puts(s, "\tSSR call failed\n"); - ++name_index; - continue; - } - ssr_success = true; - } - if (failed) - break; - - msleep(10*1000); - - /* verify ack signaling */ - if (ssr_ack_enabled) { - ssr_done_start ^= 1; - UT_ASSERT_INT(ssr_done_start, ==, - SMP2P_GET_RESTART_ACK(lhdr->flags)); - UT_ASSERT_INT(ssr_done_start, ==, - SMP2P_GET_RESTART_DONE(rhdr->flags)); - UT_ASSERT_INT(0, ==, - SMP2P_GET_RESTART_DONE(lhdr->flags)); - seq_puts(s, "\tSSR ACK Enabled and Toggled\n"); - } else { - UT_ASSERT_INT(0, ==, - SMP2P_GET_RESTART_DONE(lhdr->flags)); - UT_ASSERT_INT(0, ==, - SMP2P_GET_RESTART_ACK(lhdr->flags)); - - UT_ASSERT_INT(0, ==, - SMP2P_GET_RESTART_DONE(rhdr->flags)); - UT_ASSERT_INT(0, ==, - SMP2P_GET_RESTART_ACK(rhdr->flags)); - seq_puts(s, "\tSSR ACK Disabled\n"); - } - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -/** - * smp2p_ut_remote_ssr_ack - Verify SSR Done/ACK Feature - * - * @s: pointer to output file - * - * Triggers SSR for each subsystem. - */ -static void smp2p_ut_remote_ssr_ack(struct seq_file *s) -{ - struct smp2p_interrupt_config *int_cfg; - int pid; - - int_cfg = smp2p_get_interrupt_config(); - if (!int_cfg) { - seq_puts(s, - "Remote processor config unavailable\n"); - return; - } - - for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) { - if (!int_cfg[pid].is_configured) - continue; - - msm_smp2p_deinit_rmt_lpb_proc(pid); - smp2p_ut_remotesubsys_ssr_ack(s, pid, &int_cfg[pid]); - msm_smp2p_init_rmt_lpb_proc(pid); - } -} - -static struct dentry *dent; -static DEFINE_MUTEX(show_lock); - -static int debugfs_show(struct seq_file *s, void *data) -{ - void (*show)(struct seq_file *) = s->private; - - mutex_lock(&show_lock); - show(s); - mutex_unlock(&show_lock); - - return 0; -} - -static int debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, debugfs_show, inode->i_private); -} - -static const struct file_operations debug_ops = { - .open = debug_open, - .release = single_release, - .read = seq_read, - .llseek = seq_lseek, -}; - -void smp2p_debug_create(const char *name, - void (*show)(struct seq_file *)) -{ - struct dentry *file; - - file = debugfs_create_file(name, 0444, dent, show, &debug_ops); - if (!file) - pr_err("%s: unable to create file '%s'\n", __func__, name); -} - -void smp2p_debug_create_u32(const char *name, uint32_t *value) -{ - struct dentry *file; - - file = debugfs_create_u32(name, S_IRUGO | S_IWUSR, dent, value); - if (!file) - pr_err("%s: unable to create file '%s'\n", __func__, name); -} - -static int __init smp2p_debugfs_init(void) -{ - dent = debugfs_create_dir("smp2p_test", 0); - if (IS_ERR(dent)) - return PTR_ERR(dent); - - /* - * Add Unit Test entries. - * - * The idea with unit tests is that you can run all of them - * from ADB shell by doing: - * adb shell - * cat ut* - * - * And if particular tests fail, you can then repeatedly run the - * failing tests as you debug and resolve the failing test. - */ - smp2p_debug_create("ut_local_basic", - smp2p_ut_local_basic); - smp2p_debug_create("ut_local_late_open", - smp2p_ut_local_late_open); - smp2p_debug_create("ut_local_early_open", - smp2p_ut_local_early_open); - smp2p_debug_create("ut_mock_loopback", - smp2p_ut_mock_loopback); - smp2p_debug_create("ut_remote_inout", - smp2p_ut_remote_inout); - smp2p_debug_create("ut_local_in_max_entries", - smp2p_ut_local_in_max_entries); - smp2p_debug_create("ut_remote_out_max_entries", - smp2p_ut_remote_out_max_entries); - smp2p_debug_create("ut_local_in_multiple", - smp2p_ut_local_in_multiple); - smp2p_debug_create("ut_local_ssr_ack", - smp2p_ut_local_ssr_ack); - smp2p_debug_create("ut_remote_ssr_ack", - smp2p_ut_remote_ssr_ack); - - return 0; -} -module_init(smp2p_debugfs_init); diff --git a/drivers/soc/qcom/smp2p_test_common.h b/drivers/soc/qcom/smp2p_test_common.h deleted file mode 100644 index 3be519bc0c96..000000000000 --- a/drivers/soc/qcom/smp2p_test_common.h +++ /dev/null @@ -1,214 +0,0 @@ -/* drivers/soc/qcom/smp2p_test_common.h - * - * 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. - * - * 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 _SMP2P_TEST_COMMON_H_ -#define _SMP2P_TEST_COMMON_H_ - -#include - -/** - * Unit test assertion for logging test cases. - * - * @a lval - * @b rval - * @cmp comparison operator - * - * Assertion fails if (@a cmp @b) is not true which then - * logs the function and line number where the error occurred - * along with the values of @a and @b. - * - * Assumes that the following local variables exist: - * @s - sequential output file pointer - * @failed - set to true if test fails - */ -#define UT_ASSERT_INT(a, cmp, b) \ - { \ - int a_tmp = (a); \ - int b_tmp = (b); \ - if (!((a_tmp)cmp(b_tmp))) { \ - seq_printf(s, "%s:%d Fail: " #a "(%d) " #cmp " " #b "(%d)\n", \ - __func__, __LINE__, \ - a_tmp, b_tmp); \ - failed = 1; \ - break; \ - } \ - } - -#define UT_ASSERT_PTR(a, cmp, b) \ - { \ - void *a_tmp = (a); \ - void *b_tmp = (b); \ - if (!((a_tmp)cmp(b_tmp))) { \ - seq_printf(s, "%s:%d Fail: " #a "(%pK) " #cmp \ - " " #b "(%pK)\n", \ - __func__, __LINE__, \ - a_tmp, b_tmp); \ - failed = 1; \ - break; \ - } \ - } - -#define UT_ASSERT_UINT(a, cmp, b) \ - { \ - unsigned a_tmp = (a); \ - unsigned b_tmp = (b); \ - if (!((a_tmp)cmp(b_tmp))) { \ - seq_printf(s, "%s:%d Fail: " #a "(%u) " #cmp " " #b "(%u)\n", \ - __func__, __LINE__, \ - a_tmp, b_tmp); \ - failed = 1; \ - break; \ - } \ - } - -#define UT_ASSERT_HEX(a, cmp, b) \ - { \ - unsigned a_tmp = (a); \ - unsigned b_tmp = (b); \ - if (!((a_tmp)cmp(b_tmp))) { \ - seq_printf(s, "%s:%d Fail: " #a "(%x) " #cmp " " #b "(%x)\n", \ - __func__, __LINE__, \ - a_tmp, b_tmp); \ - failed = 1; \ - break; \ - } \ - } - -/** - * In-range unit test assertion for test cases. - * - * @a lval - * @minv Minimum value - * @maxv Maximum value - * - * Assertion fails if @a is not on the exclusive range minv, maxv - * ((@a < @minv) or (@a > @maxv)). In the failure case, the macro - * logs the function and line number where the error occurred along - * with the values of @a and @minv, @maxv. - * - * Assumes that the following local variables exist: - * @s - sequential output file pointer - * @failed - set to true if test fails - */ -#define UT_ASSERT_INT_IN_RANGE(a, minv, maxv) \ - { \ - int a_tmp = (a); \ - int minv_tmp = (minv); \ - int maxv_tmp = (maxv); \ - if (((a_tmp) < (minv_tmp)) || ((a_tmp) > (maxv_tmp))) { \ - seq_printf(s, "%s:%d Fail: " #a "(%d) < " #minv "(%d) or " \ - #a "(%d) > " #maxv "(%d)\n", \ - __func__, __LINE__, \ - a_tmp, minv_tmp, a_tmp, maxv_tmp); \ - failed = 1; \ - break; \ - } \ - } - -/* Structure to track state changes for the notifier callback. */ -struct mock_cb_data { - bool initialized; - spinlock_t lock; - struct notifier_block nb; - - /* events */ - struct completion cb_completion; - int cb_count; - int event_open; - int event_entry_update; - struct msm_smp2p_update_notif entry_data; -}; - -void smp2p_debug_create(const char *name, void (*show)(struct seq_file *)); -void smp2p_debug_create_u32(const char *name, uint32_t *value); -static inline int smp2p_test_notify(struct notifier_block *self, - unsigned long event, void *data); - -/** - * Reset mock callback data to default values. - * - * @cb: Mock callback data - */ -static inline void mock_cb_data_reset(struct mock_cb_data *cb) -{ - reinit_completion(&cb->cb_completion); - cb->cb_count = 0; - cb->event_open = 0; - cb->event_entry_update = 0; - memset(&cb->entry_data, 0, - sizeof(struct msm_smp2p_update_notif)); -} - - -/** - * Initialize mock callback data. - * - * @cb: Mock callback data - */ -static inline void mock_cb_data_init(struct mock_cb_data *cb) -{ - if (!cb->initialized) { - init_completion(&cb->cb_completion); - spin_lock_init(&cb->lock); - cb->initialized = true; - cb->nb.notifier_call = smp2p_test_notify; - memset(&cb->entry_data, 0, - sizeof(struct msm_smp2p_update_notif)); - } - mock_cb_data_reset(cb); -} - -/** - * Notifier function passed into SMP2P for testing. - * - * @self: Pointer to calling notifier block - * @event: Event - * @data: Event-specific data - * @returns: 0 - */ -static inline int smp2p_test_notify(struct notifier_block *self, - unsigned long event, void *data) -{ - struct mock_cb_data *cb_data_ptr; - unsigned long flags; - - cb_data_ptr = container_of(self, struct mock_cb_data, nb); - - spin_lock_irqsave(&cb_data_ptr->lock, flags); - - switch (event) { - case SMP2P_OPEN: - ++cb_data_ptr->event_open; - if (data) { - cb_data_ptr->entry_data = - *(struct msm_smp2p_update_notif *)(data); - } - break; - case SMP2P_ENTRY_UPDATE: - ++cb_data_ptr->event_entry_update; - if (data) { - cb_data_ptr->entry_data = - *(struct msm_smp2p_update_notif *)(data); - } - break; - default: - pr_err("%s Unknown event\n", __func__); - break; - } - - ++cb_data_ptr->cb_count; - complete(&cb_data_ptr->cb_completion); - spin_unlock_irqrestore(&cb_data_ptr->lock, flags); - return 0; -} -#endif /* _SMP2P_TEST_COMMON_H_ */ From 9d6e6eebc365fafff762ec843fa7192be82ad1db Mon Sep 17 00:00:00 2001 From: Sean Tranchetti Date: Wed, 19 Sep 2018 17:05:42 -0600 Subject: [PATCH 33/75] af_key: unconditionally clone on broadcast Attempting to avoid cloning the skb when broadcasting by inflating the refcount with sock_hold/sock_put while under RCU lock is dangerous and violates RCU principles. It leads to subtle race conditions when attempting to free the SKB, as we may reference sockets that have already been freed by the stack. Unable to handle kernel paging request at virtual address 6b6b6b6b6b6c4b [006b6b6b6b6b6c4b] address between user and kernel address ranges Internal error: Oops: 96000004 [#1] PREEMPT SMP task: fffffff78f65b380 task.stack: ffffff8049a88000 pc : sock_rfree+0x38/0x6c lr : skb_release_head_state+0x6c/0xcc Process repro (pid: 7117, stack limit = 0xffffff8049a88000) Call trace: sock_rfree+0x38/0x6c skb_release_head_state+0x6c/0xcc skb_release_all+0x1c/0x38 __kfree_skb+0x1c/0x30 kfree_skb+0xd0/0xf4 pfkey_broadcast+0x14c/0x18c pfkey_sendmsg+0x1d8/0x408 sock_sendmsg+0x44/0x60 ___sys_sendmsg+0x1d0/0x2a8 __sys_sendmsg+0x64/0xb4 SyS_sendmsg+0x34/0x4c el0_svc_naked+0x34/0x38 Kernel panic - not syncing: Fatal exception CRs-Fixed: 2251019 Change-Id: Ib3b01f941a34a7df61fe9445f746b7df33f4656a Signed-off-by: Sean Tranchetti --- net/key/af_key.c | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index 3ba903ff2bb0..58c045d027fc 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -196,30 +196,22 @@ static int pfkey_release(struct socket *sock) return 0; } -static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2, - gfp_t allocation, struct sock *sk) +static int pfkey_broadcast_one(struct sk_buff *skb, gfp_t allocation, + struct sock *sk) { int err = -ENOBUFS; - sock_hold(sk); - if (*skb2 == NULL) { - if (atomic_read(&skb->users) != 1) { - *skb2 = skb_clone(skb, allocation); - } else { - *skb2 = skb; - atomic_inc(&skb->users); - } + if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf) + return err; + + skb = skb_clone(skb, allocation); + + if (skb) { + skb_set_owner_r(skb, sk); + skb_queue_tail(&sk->sk_receive_queue, skb); + sk->sk_data_ready(sk); + err = 0; } - if (*skb2 != NULL) { - if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) { - skb_set_owner_r(*skb2, sk); - skb_queue_tail(&sk->sk_receive_queue, *skb2); - sk->sk_data_ready(sk); - *skb2 = NULL; - err = 0; - } - } - sock_put(sk); return err; } @@ -234,7 +226,6 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, { struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); struct sock *sk; - struct sk_buff *skb2 = NULL; int err = -ESRCH; /* XXX Do we need something like netlink_overrun? I think @@ -253,7 +244,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, * socket. */ if (pfk->promisc) - pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk); + pfkey_broadcast_one(skb, GFP_ATOMIC, sk); /* the exact target will be processed later */ if (sk == one_sk) @@ -268,7 +259,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, continue; } - err2 = pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk); + err2 = pfkey_broadcast_one(skb, GFP_ATOMIC, sk); /* Error is cleared after successful sending to at least one * registered KM */ @@ -278,9 +269,8 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, rcu_read_unlock(); if (one_sk != NULL) - err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk); + err = pfkey_broadcast_one(skb, allocation, one_sk); - kfree_skb(skb2); kfree_skb(skb); return err; } From c683e574fa86aca77a8d20798e9fe4ba2e76c003 Mon Sep 17 00:00:00 2001 From: Tejaswi Tanikella Date: Fri, 13 Apr 2018 12:56:57 +0530 Subject: [PATCH 34/75] pppolac: pull udp header before sock enqueue pppolac driver incorrectly enqueues the packet into the sock queue without pulling UDP headers. The application will receive data along with UDP header when L2TP control packets are received. The issue was introduced after moving UDP header removal functionality from process rcvmesg context to BH context. Instead of pppolac driver directly queuing L2TP control packets into socket queue, return packet to udp_queue_rcv_skb, which will deliver the packet to the application after pulling the UDP header. Fixes: e6afc8ace ("udp: remove headers from UDP packets before queueing") Change-Id: Icfa0fd8da43ea9c14fa7c718746a6529651ac202 Signed-off-by: Tejaswi Tanikella Signed-off-by: Chinmay Agarwal Acked-by: Sharath Chandra Vurukala --- drivers/net/ppp/pppolac.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/ppp/pppolac.c b/drivers/net/ppp/pppolac.c index 3a45cf805288..8ed809153120 100644 --- a/drivers/net/ppp/pppolac.c +++ b/drivers/net/ppp/pppolac.c @@ -83,7 +83,7 @@ static int pppolac_recv_core(struct sock *sk_udp, struct sk_buff *skb) /* Put it back if it is a control packet. */ if (skb->data[sizeof(struct udphdr)] & L2TP_CONTROL_BIT) - return opt->backlog_rcv(sk_udp, skb); + return 2; /* Skip UDP header. */ skb_pull(skb, sizeof(struct udphdr)); @@ -190,9 +190,10 @@ drop: static int pppolac_recv(struct sock *sk_udp, struct sk_buff *skb) { + int retval; sock_hold(sk_udp); - sk_receive_skb(sk_udp, skb, 0); - return 0; + retval = sk_receive_skb(sk_udp, skb, 0); + return (retval >> 1); } static struct sk_buff_head delivery_queue; From eca745fc5a2b4fcba51119b2536eb03c1ee6ac90 Mon Sep 17 00:00:00 2001 From: Banajit Goswami Date: Fri, 22 Sep 2017 11:52:35 -0700 Subject: [PATCH 35/75] ASoC: change mask in snd_soc_get/put_volsw_sx to unsigned int If the result of (min + max) is negative in functions snd_soc_get_volsw_sx() or snd_soc_put_volsw_sx(), there will be an overflow for the variable 'mask'. UBSAN: Undefined behaviour in sound/soc/soc-ops.c:382:6 signed integer overflow: -2147483648 - 1 cannot be represented in type 'int' Fix this by updating the variable type of 'mask' to unsigned int. Change-Id: Ia34f397fad5b93c0e2ffacae60e051ad20c20bdf Signed-off-by: Banajit Goswami --- sound/soc/soc-ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index c48d8c8d9766..92ccddea1fc5 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -379,7 +379,7 @@ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, unsigned int rshift = mc->rshift; int max = mc->max; int min = mc->min; - int mask = (1 << (fls(min + max) - 1)) - 1; + unsigned int mask = (1 << (fls(min + max) - 1)) - 1; unsigned int val; int ret; @@ -424,7 +424,7 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, unsigned int rshift = mc->rshift; int max = mc->max; int min = mc->min; - int mask = (1 << (fls(min + max) - 1)) - 1; + unsigned int mask = (1 << (fls(min + max) - 1)) - 1; int err = 0; unsigned int val, val_mask, val2 = 0; From c32975c88718b742aa505545ec17424b29f1337a Mon Sep 17 00:00:00 2001 From: Mohammed Nayeem Ur Rahman Date: Fri, 17 Aug 2018 12:53:43 +0530 Subject: [PATCH 36/75] msm: ADSPRPC: debugfs global and dsp file changes. Changes the naming convention and adds PID as suffix to the debugfs files. Adds debugfs file data in the tabular format and also creates global file in /sys/kernel/debug/adsprpc directory. Change-Id: I25f3f7ea59dd39c9d44d99c8503f431f10072c33 Signed-off-by: Mohammed Nayeem Ur Rahman --- drivers/char/adsprpc.c | 259 +++++++++++++++++++++++++++++++---------- 1 file changed, 196 insertions(+), 63 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 165c5707a9f7..24513e5d1e1e 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -59,7 +59,9 @@ #define VMID_SSC_Q6 38 #define VMID_ADSP_Q6 6 #define AC_VM_ADSP_HEAP_SHARED 33 -#define DEBUGFS_SIZE 1024 +#define DEBUGFS_SIZE 3072 +#define UL_SIZE 25 +#define PID_SIZE 10 #define RPC_TIMEOUT (5 * HZ) #define BALIGN 128 @@ -305,6 +307,7 @@ struct fastrpc_file { struct fastrpc_perf perf; struct dentry *debugfs_file; struct mutex map_mutex; + char *debug_buf; }; static struct fastrpc_apps gfa; @@ -2316,6 +2319,7 @@ static int fastrpc_file_free(struct fastrpc_file *fl) spin_lock(&fl->apps->hlock); hlist_del_init(&fl->hn); spin_unlock(&fl->apps->hlock); + kfree(fl->debug_buf); if (!fl->sctx) { goto bail; @@ -2473,95 +2477,217 @@ static int fastrpc_debugfs_open(struct inode *inode, struct file *filp) static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, size_t count, loff_t *position) { + struct fastrpc_apps *me = &gfa; struct fastrpc_file *fl = filp->private_data; struct hlist_node *n; struct fastrpc_buf *buf = NULL; struct fastrpc_mmap *map = NULL; + struct fastrpc_mmap *gmaps = NULL; struct smq_invoke_ctx *ictx = NULL; - struct fastrpc_channel_ctx *chan; - struct fastrpc_session_ctx *sess; + struct fastrpc_channel_ctx *chan = NULL; unsigned int len = 0; - int i, j, ret = 0; + int i, j, sess_used = 0, ret = 0; char *fileinfo = NULL; + char single_line[UL_SIZE] = "----------------"; + char title[UL_SIZE] = "========================="; fileinfo = kzalloc(DEBUGFS_SIZE, GFP_KERNEL); if (!fileinfo) goto bail; if (fl == NULL) { + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "\n%s %s %s\n", title, " CHANNEL INFO ", title); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-8s|%-9s|%-9s|%-14s|%-9s|%-13s\n", + "susbsys", "refcount", "sesscount", "issubsystemup", + "ssrcount", "session_used"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "-%s%s%s%s-\n", single_line, single_line, + single_line, single_line); for (i = 0; i < NUM_CHANNELS; i++) { + sess_used = 0; chan = &gcinfo[i]; len += scnprintf(fileinfo + len, - DEBUGFS_SIZE - len, "%s\n\n", - chan->name); + DEBUGFS_SIZE - len, "%-8s", chan->subsys); len += scnprintf(fileinfo + len, - DEBUGFS_SIZE - len, "%s %d\n", - "sesscount:", chan->sesscount); + DEBUGFS_SIZE - len, "|%-9d", + chan->kref.refcount.counter); + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, "|%-9d", + chan->sesscount); + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, "|%-14d", + chan->issubsystemup); + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, "|%-9d", + chan->ssrcount); for (j = 0; j < chan->sesscount; j++) { - sess = &chan->session[j]; - len += scnprintf(fileinfo + len, - DEBUGFS_SIZE - len, - "%s%d\n\n", "SESSION", j); - len += scnprintf(fileinfo + len, - DEBUGFS_SIZE - len, - "%s %d\n", "sid:", - sess->smmu.cb); - len += scnprintf(fileinfo + len, - DEBUGFS_SIZE - len, - "%s %d\n", "SECURE:", - sess->smmu.secure); - } + sess_used += chan->session[j].used; + } + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, "|%-13d\n", sess_used); + + } + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "\n%s%s%s\n", "=============", + " CMA HEAP ", "=============="); + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, "%-20s|%-20s\n", "addr", "size"); + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, "--%s%s---\n", + single_line, single_line); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "0x%-18llX", me->range.addr); + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, "|0x%-18llX\n", me->range.size); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "\n==========%s %s %s===========\n", + title, " GMAPS ", title); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20s|%-20s|%-20s|%-20s\n", + "fd", "phys", "size", "va"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s%s%s%s%s\n", single_line, single_line, + single_line, single_line, single_line); + hlist_for_each_entry_safe(gmaps, n, &me->maps, hn) { + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20d|0x%-18llX|0x%-18X|0x%-20lX\n\n", + gmaps->fd, gmaps->phys, + (uint32_t)gmaps->size, + gmaps->va); + } + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20s|%-20s|%-20s|%-20s\n", + "len", "refs", "raddr", "flags"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s%s%s%s%s\n", single_line, single_line, + single_line, single_line, single_line); + hlist_for_each_entry_safe(gmaps, n, &me->maps, hn) { + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "0x%-18X|%-20d|%-20lu|%-20u\n", + (uint32_t)gmaps->len, gmaps->refs, + gmaps->raddr, gmaps->flags); } } else { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %d\n\n", - "PROCESS_ID:", fl->tgid); + "\n%s %13s %d\n", "cid", ":", fl->cid); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %d\n\n", - "CHANNEL_ID:", fl->cid); + "%s %12s %d\n", "tgid", ":", fl->tgid); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %d\n\n", - "SSRCOUNT:", fl->ssrcount); + "%s %8s %d\n", "ssrcount", ":", fl->ssrcount); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s\n", - "LIST OF BUFS:"); - spin_lock(&fl->hlock); - hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) { - len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %pK %s %pK %s %llx\n", "buf:", - buf, "buf->virt:", buf->virt, - "buf->phys:", buf->phys); - } + "%s %14s %d\n", "pd", ":", fl->pd); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "\n%s\n", - "LIST OF MAPS:"); + "%s %6s %d\n", "file_close", ":", fl->file_close); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %9s %d\n", "profile", ":", fl->profile); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %3s %d\n", "smmu.coherent", ":", + fl->sctx->smmu.coherent); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %4s %d\n", "smmu.enabled", ":", + fl->sctx->smmu.enabled); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %9s %d\n", "smmu.cb", ":", fl->sctx->smmu.cb); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %5s %d\n", "smmu.secure", ":", + fl->sctx->smmu.secure); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %5s %d\n", "smmu.faults", ":", + fl->sctx->smmu.faults); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %s %d\n", "link.link_state", + ":", *&me->channel[fl->cid].link.link_state); + + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "\n=======%s %s %s======\n", title, + " LIST OF MAPS ", title); + + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20s|%-20s|%-20s\n", "va", "phys", "size"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s%s%s%s%s\n", + single_line, single_line, single_line, + single_line, single_line); hlist_for_each_entry_safe(map, n, &fl->maps, hn) { - len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %pK %s %lx %s %llx\n", - "map:", map, - "map->va:", map->va, - "map->phys:", map->phys); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "0x%-20lX|0x%-20llX|0x%-20zu\n\n", + map->va, map->phys, + map->size); } len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "\n%s\n", - "LIST OF PENDING SMQCONTEXTS:"); + "%-20s|%-20s|%-20s|%-20s\n", + "len", "refs", + "raddr", "uncached"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s%s%s%s%s\n", + single_line, single_line, single_line, + single_line, single_line); + hlist_for_each_entry_safe(map, n, &fl->maps, hn) { + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20zu|%-20d|0x%-20lX|%-20d\n\n", + map->len, map->refs, map->raddr, + map->uncached); + } + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20s|%-20s\n", "secure", "attr"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s%s%s%s%s\n", + single_line, single_line, single_line, + single_line, single_line); + hlist_for_each_entry_safe(map, n, &fl->maps, hn) { + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20d|0x%-20lX\n\n", + map->secure, map->attr); + } + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "\n======%s %s %s======\n", title, + " LIST OF BUFS ", title); + spin_lock(&fl->hlock); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-19s|%-19s|%-19s\n", + "virt", "phys", "size"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s%s%s%s%s\n", single_line, single_line, + single_line, single_line, single_line); + hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) { + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, + "0x%-17p|0x%-17llX|%-19zu\n", + buf->virt, (uint64_t)buf->phys, buf->size); + } + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "\n%s %s %s\n", title, + " LIST OF PENDING SMQCONTEXTS ", title); + + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20s|%-10s|%-10s|%-10s|%-20s\n", + "sc", "pid", "tgid", "used", "ctxid"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s%s%s%s%s\n", single_line, single_line, + single_line, single_line, single_line); hlist_for_each_entry_safe(ictx, n, &fl->clst.pending, hn) { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %pK %s %u %s %u %s %u\n", - "smqcontext:", ictx, - "sc:", ictx->sc, - "tid:", ictx->pid, - "handle", ictx->rpra->h); + "0x%-18X|%-10d|%-10d|%-10zu|0x%-20llX\n\n", + ictx->sc, ictx->pid, ictx->tgid, + ictx->used, ictx->ctxid); } + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "\n%s\n", - "LIST OF INTERRUPTED SMQCONTEXTS:"); + "\n%s %s %s\n", title, + " LIST OF INTERRUPTED SMQCONTEXTS ", title); + + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20s|%-10s|%-10s|%-10s|%-20s\n", + "sc", "pid", "tgid", "used", "ctxid"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s%s%s%s%s\n", single_line, single_line, + single_line, single_line, single_line); hlist_for_each_entry_safe(ictx, n, &fl->clst.interrupted, hn) { - len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %pK %s %u %s %u %s %u\n", - "smqcontext:", ictx, - "sc:", ictx->sc, - "tid:", ictx->pid, - "handle", ictx->rpra->h); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20u|%-20d|%-20d|%-20zu|0x%-20llX\n\n", + ictx->sc, ictx->pid, ictx->tgid, + ictx->used, ictx->ctxid); } spin_unlock(&fl->hlock); } @@ -2657,12 +2783,20 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) struct dentry *debugfs_file; struct fastrpc_file *fl = NULL; struct fastrpc_apps *me = &gfa; + char strpid[PID_SIZE]; + int buf_size = 0; VERIFY(err, NULL != (fl = kzalloc(sizeof(*fl), GFP_KERNEL))); if (err) return err; - debugfs_file = debugfs_create_file(current->comm, 0644, debugfs_root, - fl, &debugfs_fops); + snprintf(strpid, PID_SIZE, "%d", current->pid); + buf_size = strlen(current->comm) + strlen(strpid) + 1; + fl->debug_buf = kzalloc(buf_size, GFP_KERNEL); + snprintf(fl->debug_buf, UL_SIZE, "%.10s%s%d", + current->comm, "_", current->pid); + debugfs_file = debugfs_create_file(fl->debug_buf, 0644, + debugfs_root, fl, &debugfs_fops); + context_list_ctor(&fl->clst); spin_lock_init(&fl->hlock); INIT_HLIST_HEAD(&fl->maps); @@ -3176,8 +3310,8 @@ static int __init fastrpc_device_init(void) struct device *dev = NULL; int err = 0, i; + debugfs_root = debugfs_create_dir("adsprpc", NULL); memset(me, 0, sizeof(*me)); - fastrpc_init(me); me->dev = NULL; VERIFY(err, 0 == platform_driver_register(&fastrpc_driver)); @@ -3216,12 +3350,11 @@ static int __init fastrpc_device_init(void) gcinfo[i].subsys, &me->channel[i].nb); } - me->client = msm_ion_client_create(DEVICE_NAME); VERIFY(err, !IS_ERR_OR_NULL(me->client)); if (err) goto device_create_bail; - debugfs_root = debugfs_create_dir("adsprpc", NULL); + return 0; device_create_bail: for (i = 0; i < NUM_CHANNELS; i++) { From 4ed2bedbea9cd9ac895ffa2aa0f527b2742201d8 Mon Sep 17 00:00:00 2001 From: Rohit kumar Date: Thu, 9 Aug 2018 18:21:50 +0530 Subject: [PATCH 37/75] ASoC: Fix UBSAN warning at snd_soc_get/put_volsw_sx() In functions snd_soc_get_volsw_sx() or snd_soc_put_volsw_sx(), if the result of (min + max) is negative, then fls() returns signed integer with value as 32. This leads to signed integer overflow as complete operation is considered as signed integer. UBSAN: Undefined behaviour in sound/soc/soc-ops.c:382:50 signed integer overflow: -2147483648 - 1 cannot be represented in type 'int' Call trace: [] __dump_stack lib/dump_stack.c:15 [inline] [] dump_stack+0xec/0x158 lib/dump_stack.c:51 [] ubsan_epilogue+0x18/0x50 lib/ubsan.c:164 [] handle_overflow+0xf8/0x130 lib/ubsan.c:195 [] __ubsan_handle_sub_overflow+0x34/0x44 lib/ubsan.c:211 [] snd_soc_get_volsw_sx+0x1a8/0x1f8 sound/soc/soc-ops.c:382 Typecast the operation to unsigned int to fix the issue. Change-Id: I40d070b1357f016eb1622146180e4abb340e5d00 Signed-off-by: Rohit kumar Signed-off-by: Mark Brown Git-commit: ae7d1247d8673ebfd686b17e759d4be391165368 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Rohit kumar --- sound/soc/soc-ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 92ccddea1fc5..c7d60e532461 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -379,7 +379,7 @@ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, unsigned int rshift = mc->rshift; int max = mc->max; int min = mc->min; - unsigned int mask = (1 << (fls(min + max) - 1)) - 1; + unsigned int mask = (1U << (fls(min + max) - 1)) - 1; unsigned int val; int ret; @@ -424,7 +424,7 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, unsigned int rshift = mc->rshift; int max = mc->max; int min = mc->min; - unsigned int mask = (1 << (fls(min + max) - 1)) - 1; + unsigned int mask = (1U << (fls(min + max) - 1)) - 1; int err = 0; unsigned int val, val_mask, val2 = 0; From b253ca5007325d8859015bc3cc53a65247830987 Mon Sep 17 00:00:00 2001 From: Sean Tranchetti Date: Wed, 19 Sep 2018 17:05:42 -0600 Subject: [PATCH 38/75] af_key: unconditionally clone on broadcast Attempting to avoid cloning the skb when broadcasting by inflating the refcount with sock_hold/sock_put while under RCU lock is dangerous and violates RCU principles. It leads to subtle race conditions when attempting to free the SKB, as we may reference sockets that have already been freed by the stack. Unable to handle kernel paging request at virtual address 6b6b6b6b6b6c4b [006b6b6b6b6b6c4b] address between user and kernel address ranges Internal error: Oops: 96000004 [#1] PREEMPT SMP task: fffffff78f65b380 task.stack: ffffff8049a88000 pc : sock_rfree+0x38/0x6c lr : skb_release_head_state+0x6c/0xcc Process repro (pid: 7117, stack limit = 0xffffff8049a88000) Call trace: sock_rfree+0x38/0x6c skb_release_head_state+0x6c/0xcc skb_release_all+0x1c/0x38 __kfree_skb+0x1c/0x30 kfree_skb+0xd0/0xf4 pfkey_broadcast+0x14c/0x18c pfkey_sendmsg+0x1d8/0x408 sock_sendmsg+0x44/0x60 ___sys_sendmsg+0x1d0/0x2a8 __sys_sendmsg+0x64/0xb4 SyS_sendmsg+0x34/0x4c el0_svc_naked+0x34/0x38 Kernel panic - not syncing: Fatal exception CRs-Fixed: 2251019 Change-Id: Ib3b01f941a34a7df61fe9445f746b7df33f4656a Signed-off-by: Sean Tranchetti --- net/key/af_key.c | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index 3ba903ff2bb0..58c045d027fc 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -196,30 +196,22 @@ static int pfkey_release(struct socket *sock) return 0; } -static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2, - gfp_t allocation, struct sock *sk) +static int pfkey_broadcast_one(struct sk_buff *skb, gfp_t allocation, + struct sock *sk) { int err = -ENOBUFS; - sock_hold(sk); - if (*skb2 == NULL) { - if (atomic_read(&skb->users) != 1) { - *skb2 = skb_clone(skb, allocation); - } else { - *skb2 = skb; - atomic_inc(&skb->users); - } + if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf) + return err; + + skb = skb_clone(skb, allocation); + + if (skb) { + skb_set_owner_r(skb, sk); + skb_queue_tail(&sk->sk_receive_queue, skb); + sk->sk_data_ready(sk); + err = 0; } - if (*skb2 != NULL) { - if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) { - skb_set_owner_r(*skb2, sk); - skb_queue_tail(&sk->sk_receive_queue, *skb2); - sk->sk_data_ready(sk); - *skb2 = NULL; - err = 0; - } - } - sock_put(sk); return err; } @@ -234,7 +226,6 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, { struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); struct sock *sk; - struct sk_buff *skb2 = NULL; int err = -ESRCH; /* XXX Do we need something like netlink_overrun? I think @@ -253,7 +244,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, * socket. */ if (pfk->promisc) - pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk); + pfkey_broadcast_one(skb, GFP_ATOMIC, sk); /* the exact target will be processed later */ if (sk == one_sk) @@ -268,7 +259,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, continue; } - err2 = pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk); + err2 = pfkey_broadcast_one(skb, GFP_ATOMIC, sk); /* Error is cleared after successful sending to at least one * registered KM */ @@ -278,9 +269,8 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, rcu_read_unlock(); if (one_sk != NULL) - err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk); + err = pfkey_broadcast_one(skb, allocation, one_sk); - kfree_skb(skb2); kfree_skb(skb); return err; } From 87c4ed87e3cef20b616783c5e5fe8a9588f4fb9a Mon Sep 17 00:00:00 2001 From: Narender Ankam Date: Thu, 30 Aug 2018 21:45:59 +0530 Subject: [PATCH 39/75] msm: mdss: dsi: fix slab-out-of-bounds issue While handling dsi_gen_read_status, status buffer was xlogging without checking for its max size. Add proper conditional check to xlog status buffer. Change-Id: Ia5a1fe18de123d2911c31ae79492b96f67e1273d Signed-off-by: Narender Ankam --- drivers/video/fbdev/msm/mdss_dsi_panel.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index 5ba0480436a2..bf695ae0beaf 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -1803,17 +1803,13 @@ static bool mdss_dsi_cmp_panel_reg_v2(struct mdss_dsi_ctrl_pdata *ctrl) for (i = 0; i < ctrl->status_cmds.cmd_cnt; i++) len += lenp[i]; - for (i = 0; i < len; i++) { - pr_debug("[%i] return:0x%x status:0x%x\n", - i, (unsigned int)ctrl->return_buf[i], - (unsigned int)ctrl->status_value[j + i]); - MDSS_XLOG(ctrl->ndx, ctrl->return_buf[i], - ctrl->status_value[j + i]); - j += len; - } - for (j = 0; j < ctrl->groups; ++j) { for (i = 0; i < len; ++i) { + pr_debug("[%i] return:0x%x status:0x%x\n", + i, ctrl->return_buf[i], + (unsigned int)ctrl->status_value[group + i]); + MDSS_XLOG(ctrl->ndx, ctrl->return_buf[i], + ctrl->status_value[group + i]); if (ctrl->return_buf[i] != ctrl->status_value[group + i]) break; From e0ce9d1bb01d03b44845990d5336c98ba312ad38 Mon Sep 17 00:00:00 2001 From: Hardik Kantilal Patel Date: Tue, 14 Aug 2018 10:39:25 +0530 Subject: [PATCH 40/75] icnss: Remove WARN_ON during self recovery trigger Remove WARN_ON during self recovery trigger to avoid false positive while doing stress testing of self recovery feature. CRs-Fixed: 2296234 Change-Id: Ibe858f74ccb78565c98ba249a244f6bceb0ca1e5 Signed-off-by: Hardik Kantilal Patel --- drivers/soc/qcom/icnss.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index e0fa8b7720d2..81c3befa0812 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -3456,7 +3456,6 @@ int icnss_trigger_recovery(struct device *dev) goto out; } - WARN_ON(1); icnss_pr_warn("Initiate PD restart at WLAN FW, state: 0x%lx\n", priv->state); From 95645a63ac482fb03e9a1a903d5ac4b35fb9d684 Mon Sep 17 00:00:00 2001 From: Kaushal Kumar Date: Tue, 27 Mar 2018 18:08:32 +0530 Subject: [PATCH 41/75] soc: qcom: scm: Add a noretry variant for scm_call2 scm_call2 can block scm calls up to 2s due to its retry mechanism whenever the secure firmware is busy waiting for certain processing by the client who in turn is waiting upon its scm call to either complete or return with failure. Upon early return, client can process the pending requests to free up secure firmware and unblock processing of all pending scm calls. Add a noretry variant for scm_call2 which can be used by clients who do not intend to wait for 2s for return status. Change-Id: I1f0849464a64c32a4de4510fa5787b0ab328725c Signed-off-by: Kaushal Kumar --- drivers/soc/qcom/scm.c | 70 ++++++++++++++++++++++++++---------------- include/soc/qcom/scm.h | 9 +++++- 2 files changed, 52 insertions(+), 27 deletions(-) diff --git a/drivers/soc/qcom/scm.c b/drivers/soc/qcom/scm.c index c6bdcee8131e..f4125113efff 100644 --- a/drivers/soc/qcom/scm.c +++ b/drivers/soc/qcom/scm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2018, 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 @@ -635,28 +635,7 @@ static int allocate_extra_arg_buffer(struct scm_desc *desc, gfp_t flags) return 0; } -/** - * scm_call2() - Invoke a syscall in the secure world - * @fn_id: The function ID for this syscall - * @desc: Descriptor structure containing arguments and return values - * - * Sends a command to the SCM and waits for the command to finish processing. - * This should *only* be called in pre-emptible context. - * - * A note on cache maintenance: - * Note that any buffers that are expected to be accessed by the secure world - * must be flushed before invoking scm_call and invalidated in the cache - * immediately after scm_call returns. An important point that must be noted - * is that on ARMV8 architectures, invalidation actually also causes a dirty - * cache line to be cleaned (flushed + unset-dirty-bit). Therefore it is of - * paramount importance that the buffer be flushed before invoking scm_call2, - * even if you don't care about the contents of that buffer. - * - * Note that cache maintenance on the argument buffer (desc->args) is taken care - * of by scm_call2; however, callers are responsible for any other cached - * buffers passed over to the secure world. -*/ -int scm_call2(u32 fn_id, struct scm_desc *desc) +static int __scm_call2(u32 fn_id, struct scm_desc *desc, bool retry) { int arglen = desc->arginfo & 0xf; int ret, retry_count = 0; @@ -670,7 +649,6 @@ int scm_call2(u32 fn_id, struct scm_desc *desc) return ret; x0 = fn_id | scm_version_mask; - do { mutex_lock(&scm_lock); @@ -700,13 +678,15 @@ int scm_call2(u32 fn_id, struct scm_desc *desc) mutex_unlock(&scm_lmh_lock); mutex_unlock(&scm_lock); + if (!retry) + goto out; if (ret == SCM_V2_EBUSY) msleep(SCM_EBUSY_WAIT_MS); if (retry_count == 33) pr_warn("scm: secure world has been busy for 1 second!\n"); - } while (ret == SCM_V2_EBUSY && (retry_count++ < SCM_EBUSY_MAX_RETRY)); - + } while (ret == SCM_V2_EBUSY && (retry_count++ < SCM_EBUSY_MAX_RETRY)); +out: if (ret < 0) pr_err("scm_call failed: func id %#llx, ret: %d, syscall returns: %#llx, %#llx, %#llx\n", x0, ret, desc->ret[0], desc->ret[1], desc->ret[2]); @@ -717,8 +697,46 @@ int scm_call2(u32 fn_id, struct scm_desc *desc) return scm_remap_error(ret); return 0; } + +/** + * scm_call2() - Invoke a syscall in the secure world + * @fn_id: The function ID for this syscall + * @desc: Descriptor structure containing arguments and return values + * + * Sends a command to the SCM and waits for the command to finish processing. + * This should *only* be called in pre-emptible context. + * + * A note on cache maintenance: + * Note that any buffers that are expected to be accessed by the secure world + * must be flushed before invoking scm_call and invalidated in the cache + * immediately after scm_call returns. An important point that must be noted + * is that on ARMV8 architectures, invalidation actually also causes a dirty + * cache line to be cleaned (flushed + unset-dirty-bit). Therefore it is of + * paramount importance that the buffer be flushed before invoking scm_call2, + * even if you don't care about the contents of that buffer. + * + * Note that cache maintenance on the argument buffer (desc->args) is taken care + * of by scm_call2; however, callers are responsible for any other cached + * buffers passed over to the secure world. + */ +int scm_call2(u32 fn_id, struct scm_desc *desc) +{ + return __scm_call2(fn_id, desc, true); +} EXPORT_SYMBOL(scm_call2); +/** + * scm_call2_noretry() - Invoke a syscall in the secure world + * + * Similar to scm_call2 except that there is no retry mechanism + * implemented. + */ +int scm_call2_noretry(u32 fn_id, struct scm_desc *desc) +{ + return __scm_call2(fn_id, desc, false); +} +EXPORT_SYMBOL(scm_call2_noretry); + /** * scm_call2_atomic() - Invoke a syscall in the secure world * diff --git a/include/soc/qcom/scm.h b/include/soc/qcom/scm.h index f0a3124dae00..e741d540a8d6 100644 --- a/include/soc/qcom/scm.h +++ b/include/soc/qcom/scm.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2018, 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 @@ -101,6 +101,8 @@ extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, extern int scm_call2(u32 cmd_id, struct scm_desc *desc); +extern int scm_call2_noretry(u32 cmd_id, struct scm_desc *desc); + extern int scm_call2_atomic(u32 cmd_id, struct scm_desc *desc); extern int scm_call_noalloc(u32 svc_id, u32 cmd_id, const void *cmd_buf, @@ -150,6 +152,11 @@ static inline int scm_call2(u32 cmd_id, struct scm_desc *desc) return 0; } +static inline int scm_call2_noretry(u32 cmd_id, struct scm_desc *desc) +{ + return 0; +} + static inline int scm_call2_atomic(u32 cmd_id, struct scm_desc *desc) { return 0; From 3c59fd3182acf9e4c1f8019e56b40fccfb8d5f71 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Thu, 19 Jul 2018 18:08:35 -0700 Subject: [PATCH 42/75] ANDROID: sdcardfs: Don't use OVERRIDE_CRED macro The macro hides some control flow, making it easier to run into bugs. bug: 111642636 Change-Id: I37ec207c277d97c4e7f1e8381bc9ae743ad78435 Reported-by: Jann Horn Signed-off-by: Daniel Rosenberg Git-commit: e1a7c83cfd36c26e208c72740a045a8fe79aee44 Git-repo: https://android.googlesource.com/kernel/common/ Signed-off-by: Ritesh Harjani Signed-off-by: Srinivasa Rao Kuppala --- fs/sdcardfs/file.c | 24 +++-- fs/sdcardfs/inode.c | 198 +++++++++-------------------------------- fs/sdcardfs/lookup.c | 9 +- fs/sdcardfs/sdcardfs.h | 25 ------ 4 files changed, 66 insertions(+), 190 deletions(-) diff --git a/fs/sdcardfs/file.c b/fs/sdcardfs/file.c index 1461254f301d..271c4c4cb760 100644 --- a/fs/sdcardfs/file.c +++ b/fs/sdcardfs/file.c @@ -118,7 +118,11 @@ static long sdcardfs_unlocked_ioctl(struct file *file, unsigned int cmd, goto out; /* save current_cred and override it */ - OVERRIDE_CRED(sbi, saved_cred, SDCARDFS_I(file_inode(file))); + saved_cred = override_fsids(sbi, SDCARDFS_I(file_inode(file))->data); + if (!saved_cred) { + err = -ENOMEM; + goto out; + } if (lower_file->f_op->unlocked_ioctl) err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg); @@ -127,7 +131,7 @@ static long sdcardfs_unlocked_ioctl(struct file *file, unsigned int cmd, if (!err) sdcardfs_copy_and_fix_attrs(file_inode(file), file_inode(lower_file)); - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out: return err; } @@ -149,12 +153,16 @@ static long sdcardfs_compat_ioctl(struct file *file, unsigned int cmd, goto out; /* save current_cred and override it */ - OVERRIDE_CRED(sbi, saved_cred, SDCARDFS_I(file_inode(file))); + saved_cred = override_fsids(sbi, SDCARDFS_I(file_inode(file))->data); + if (!saved_cred) { + err = -ENOMEM; + goto out; + } if (lower_file->f_op->compat_ioctl) err = lower_file->f_op->compat_ioctl(lower_file, cmd, arg); - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out: return err; } @@ -241,7 +249,11 @@ static int sdcardfs_open(struct inode *inode, struct file *file) } /* save current_cred and override it */ - OVERRIDE_CRED(sbi, saved_cred, SDCARDFS_I(inode)); + saved_cred = override_fsids(sbi, SDCARDFS_I(inode)->data); + if (!saved_cred) { + err = -ENOMEM; + goto out_err; + } file->private_data = kzalloc(sizeof(struct sdcardfs_file_info), GFP_KERNEL); @@ -271,7 +283,7 @@ static int sdcardfs_open(struct inode *inode, struct file *file) sdcardfs_copy_and_fix_attrs(inode, sdcardfs_lower_inode(inode)); out_revert_cred: - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out_err: dput(parent); return err; diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index b41eb7fa37bb..0d965912a725 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -22,7 +22,6 @@ #include #include -/* Do not directly use this function. Use OVERRIDE_CRED() instead. */ const struct cred *override_fsids(struct sdcardfs_sb_info *sbi, struct sdcardfs_inode_data *data) { @@ -50,7 +49,6 @@ const struct cred *override_fsids(struct sdcardfs_sb_info *sbi, return old_cred; } -/* Do not directly use this function, use REVERT_CRED() instead. */ void revert_fsids(const struct cred *old_cred) { const struct cred *cur_cred; @@ -78,7 +76,10 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, } /* save current_cred and override it */ - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir)); + saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb), + SDCARDFS_I(dir)->data); + if (!saved_cred) + return -ENOMEM; sdcardfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; @@ -115,53 +116,11 @@ out: out_unlock: unlock_dir(lower_parent_dentry); sdcardfs_put_lower_path(dentry, &lower_path); - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out_eacces: return err; } -#if 0 -static int sdcardfs_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry) -{ - struct dentry *lower_old_dentry; - struct dentry *lower_new_dentry; - struct dentry *lower_dir_dentry; - u64 file_size_save; - int err; - struct path lower_old_path, lower_new_path; - - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb)); - - file_size_save = i_size_read(d_inode(old_dentry)); - sdcardfs_get_lower_path(old_dentry, &lower_old_path); - sdcardfs_get_lower_path(new_dentry, &lower_new_path); - lower_old_dentry = lower_old_path.dentry; - lower_new_dentry = lower_new_path.dentry; - lower_dir_dentry = lock_parent(lower_new_dentry); - - err = vfs_link(lower_old_dentry, d_inode(lower_dir_dentry), - lower_new_dentry, NULL); - if (err || !d_inode(lower_new_dentry)) - goto out; - - err = sdcardfs_interpose(new_dentry, dir->i_sb, &lower_new_path); - if (err) - goto out; - fsstack_copy_attr_times(dir, d_inode(lower_new_dentry)); - fsstack_copy_inode_size(dir, d_inode(lower_new_dentry)); - set_nlink(d_inode(old_dentry), - sdcardfs_lower_inode(d_inode(old_dentry))->i_nlink); - i_size_write(d_inode(new_dentry), file_size_save); -out: - unlock_dir(lower_dir_dentry); - sdcardfs_put_lower_path(old_dentry, &lower_old_path); - sdcardfs_put_lower_path(new_dentry, &lower_new_path); - REVERT_CRED(); - return err; -} -#endif - static int sdcardfs_unlink(struct inode *dir, struct dentry *dentry) { int err; @@ -178,7 +137,10 @@ static int sdcardfs_unlink(struct inode *dir, struct dentry *dentry) } /* save current_cred and override it */ - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir)); + saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb), + SDCARDFS_I(dir)->data); + if (!saved_cred) + return -ENOMEM; sdcardfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; @@ -209,43 +171,11 @@ out: unlock_dir(lower_dir_dentry); dput(lower_dentry); sdcardfs_put_lower_path(dentry, &lower_path); - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out_eacces: return err; } -#if 0 -static int sdcardfs_symlink(struct inode *dir, struct dentry *dentry, - const char *symname) -{ - int err; - struct dentry *lower_dentry; - struct dentry *lower_parent_dentry = NULL; - struct path lower_path; - - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb)); - - sdcardfs_get_lower_path(dentry, &lower_path); - lower_dentry = lower_path.dentry; - lower_parent_dentry = lock_parent(lower_dentry); - - err = vfs_symlink(d_inode(lower_parent_dentry), lower_dentry, symname); - if (err) - goto out; - err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path); - if (err) - goto out; - fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir)); - fsstack_copy_inode_size(dir, d_inode(lower_parent_dentry)); - -out: - unlock_dir(lower_parent_dentry); - sdcardfs_put_lower_path(dentry, &lower_path); - REVERT_CRED(); - return err; -} -#endif - static int touch(char *abs_path, mode_t mode) { struct file *filp = filp_open(abs_path, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, mode); @@ -287,7 +217,10 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode } /* save current_cred and override it */ - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir)); + saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb), + SDCARDFS_I(dir)->data); + if (!saved_cred) + return -ENOMEM; /* check disk space */ parent_dentry = dget_parent(dentry); @@ -366,13 +299,21 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode if (make_nomedia_in_obb || ((pd->perm == PERM_ANDROID) && (qstr_case_eq(&dentry->d_name, &q_data)))) { - REVERT_CRED(saved_cred); - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(d_inode(dentry))); + revert_fsids(saved_cred); + saved_cred = override_fsids(sbi, + SDCARDFS_I(d_inode(dentry))->data); + if (!saved_cred) { + pr_err("sdcardfs: failed to set up .nomedia in %s: %d\n", + lower_path.dentry->d_name.name, + -ENOMEM); + goto out; + } set_fs_pwd(current->fs, &lower_path); touch_err = touch(".nomedia", 0664); if (touch_err) { pr_err("sdcardfs: failed to create .nomedia in %s: %d\n", - lower_path.dentry->d_name.name, touch_err); + lower_path.dentry->d_name.name, + touch_err); goto out; } } @@ -382,7 +323,7 @@ out: out_unlock: sdcardfs_put_lower_path(dentry, &lower_path); out_revert: - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out_eacces: return err; } @@ -402,7 +343,10 @@ static int sdcardfs_rmdir(struct inode *dir, struct dentry *dentry) } /* save current_cred and override it */ - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir)); + saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb), + SDCARDFS_I(dir)->data); + if (!saved_cred) + return -ENOMEM; /* sdcardfs_get_real_lower(): in case of remove an user's obb dentry * the dentry on the original path should be deleted. @@ -427,44 +371,11 @@ static int sdcardfs_rmdir(struct inode *dir, struct dentry *dentry) out: unlock_dir(lower_dir_dentry); sdcardfs_put_real_lower(dentry, &lower_path); - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out_eacces: return err; } -#if 0 -static int sdcardfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, - dev_t dev) -{ - int err; - struct dentry *lower_dentry; - struct dentry *lower_parent_dentry = NULL; - struct path lower_path; - - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb)); - - sdcardfs_get_lower_path(dentry, &lower_path); - lower_dentry = lower_path.dentry; - lower_parent_dentry = lock_parent(lower_dentry); - - err = vfs_mknod(d_inode(lower_parent_dentry), lower_dentry, mode, dev); - if (err) - goto out; - - err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path); - if (err) - goto out; - fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir)); - fsstack_copy_inode_size(dir, d_inode(lower_parent_dentry)); - -out: - unlock_dir(lower_parent_dentry); - sdcardfs_put_lower_path(dentry, &lower_path); - REVERT_CRED(); - return err; -} -#endif - /* * The locking rules in sdcardfs_rename are complex. We could use a simpler * superblock-level name-space lock for renames and copy-ups. @@ -489,7 +400,10 @@ static int sdcardfs_rename(struct inode *old_dir, struct dentry *old_dentry, } /* save current_cred and override it */ - OVERRIDE_CRED(SDCARDFS_SB(old_dir->i_sb), saved_cred, SDCARDFS_I(new_dir)); + saved_cred = override_fsids(SDCARDFS_SB(old_dir->i_sb), + SDCARDFS_I(new_dir)->data); + if (!saved_cred) + return -ENOMEM; sdcardfs_get_real_lower(old_dentry, &lower_old_path); sdcardfs_get_lower_path(new_dentry, &lower_new_path); @@ -536,7 +450,7 @@ out: dput(lower_new_dir_dentry); sdcardfs_put_real_lower(old_dentry, &lower_old_path); sdcardfs_put_lower_path(new_dentry, &lower_new_path); - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out_eacces: return err; } @@ -655,33 +569,7 @@ static int sdcardfs_permission(struct vfsmount *mnt, struct inode *inode, int ma if (IS_POSIXACL(inode)) pr_warn("%s: This may be undefined behavior...\n", __func__); err = generic_permission(&tmp, mask); - /* XXX - * Original sdcardfs code calls inode_permission(lower_inode,.. ) - * for checking inode permission. But doing such things here seems - * duplicated work, because the functions called after this func, - * such as vfs_create, vfs_unlink, vfs_rename, and etc, - * does exactly same thing, i.e., they calls inode_permission(). - * So we just let they do the things. - * If there are any security hole, just uncomment following if block. - */ -#if 0 - if (!err) { - /* - * Permission check on lower_inode(=EXT4). - * we check it with AID_MEDIA_RW permission - */ - struct inode *lower_inode; - - OVERRIDE_CRED(SDCARDFS_SB(inode->sb)); - - lower_inode = sdcardfs_lower_inode(inode); - err = inode_permission(lower_inode, mask); - - REVERT_CRED(); - } -#endif return err; - } static int sdcardfs_setattr_wrn(struct dentry *dentry, struct iattr *ia) @@ -756,7 +644,10 @@ static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct goto out_err; /* save current_cred and override it */ - OVERRIDE_CRED(SDCARDFS_SB(dentry->d_sb), saved_cred, SDCARDFS_I(inode)); + saved_cred = override_fsids(SDCARDFS_SB(dentry->d_sb), + SDCARDFS_I(inode)->data); + if (!saved_cred) + return -ENOMEM; sdcardfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; @@ -815,7 +706,7 @@ static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct out: sdcardfs_put_lower_path(dentry, &lower_path); - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out_err: return err; } @@ -898,13 +789,6 @@ const struct inode_operations sdcardfs_dir_iops = { .setattr = sdcardfs_setattr_wrn, .setattr2 = sdcardfs_setattr, .getattr = sdcardfs_getattr, - /* XXX Following operations are implemented, - * but FUSE(sdcard) or FAT does not support them - * These methods are *NOT* perfectly tested. - .symlink = sdcardfs_symlink, - .link = sdcardfs_link, - .mknod = sdcardfs_mknod, - */ }; const struct inode_operations sdcardfs_main_iops = { diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c index 206f8cbc7d7d..a671ae2338ea 100644 --- a/fs/sdcardfs/lookup.c +++ b/fs/sdcardfs/lookup.c @@ -426,7 +426,12 @@ struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry, } /* save current_cred and override it */ - OVERRIDE_CRED_PTR(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir)); + saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb), + SDCARDFS_I(dir)->data); + if (!saved_cred) { + ret = ERR_PTR(-ENOMEM); + goto out_err; + } sdcardfs_get_lower_path(parent, &lower_parent_path); @@ -457,7 +462,7 @@ struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry, out: sdcardfs_put_lower_path(parent, &lower_parent_path); - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out_err: dput(parent); return ret; diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h index 055e413509e4..99227a07a8d6 100644 --- a/fs/sdcardfs/sdcardfs.h +++ b/fs/sdcardfs/sdcardfs.h @@ -88,31 +88,6 @@ (x)->i_mode = ((x)->i_mode & S_IFMT) | 0775;\ } while (0) -/* OVERRIDE_CRED() and REVERT_CRED() - * OVERRIDE_CRED() - * backup original task->cred - * and modifies task->cred->fsuid/fsgid to specified value. - * REVERT_CRED() - * restore original task->cred->fsuid/fsgid. - * These two macro should be used in pair, and OVERRIDE_CRED() should be - * placed at the beginning of a function, right after variable declaration. - */ -#define OVERRIDE_CRED(sdcardfs_sbi, saved_cred, info) \ - do { \ - saved_cred = override_fsids(sdcardfs_sbi, info->data); \ - if (!saved_cred) \ - return -ENOMEM; \ - } while (0) - -#define OVERRIDE_CRED_PTR(sdcardfs_sbi, saved_cred, info) \ - do { \ - saved_cred = override_fsids(sdcardfs_sbi, info->data); \ - if (!saved_cred) \ - return ERR_PTR(-ENOMEM); \ - } while (0) - -#define REVERT_CRED(saved_cred) revert_fsids(saved_cred) - /* Android 5.0 support */ /* Permission mode for a specific node. Controls how file permissions From 62b5592573ac0e1f77677728e0f9cdb275cccf82 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Fri, 20 Jul 2018 16:11:40 -0700 Subject: [PATCH 43/75] ANDROID: sdcardfs: Change current->fs under lock Adjusted from previous version to add missing include bug: 111641492 Change-Id: I321d83f5d599efb3abdfaf2f3a4900ac512beca6 Reported-by: Jann Horn Signed-off-by: Daniel Rosenberg Git-commit: f6d0920c41a732be06d284177311b57335227bd1 Git-repo: https://android.googlesource.com/kernel/common/ Signed-off-by: Ritesh Harjani --- fs/sdcardfs/inode.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index 0d965912a725..cc9409ceaa32 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -21,6 +21,7 @@ #include "sdcardfs.h" #include #include +#include const struct cred *override_fsids(struct sdcardfs_sb_info *sbi, struct sdcardfs_inode_data *data) @@ -96,8 +97,11 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, err = -ENOMEM; goto out_unlock; } + copied_fs->umask = 0; + task_lock(current); current->fs = copied_fs; - current->fs->umask = 0; + task_unlock(current); + err = vfs_create2(lower_dentry_mnt, d_inode(lower_parent_dentry), lower_dentry, mode, want_excl); if (err) goto out; @@ -111,7 +115,9 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, fixup_lower_ownership(dentry, dentry->d_name.name); out: + task_lock(current); current->fs = saved_fs; + task_unlock(current); free_fs_struct(copied_fs); out_unlock: unlock_dir(lower_parent_dentry); @@ -249,8 +255,11 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode unlock_dir(lower_parent_dentry); goto out_unlock; } + copied_fs->umask = 0; + task_lock(current); current->fs = copied_fs; - current->fs->umask = 0; + task_unlock(current); + err = vfs_mkdir2(lower_mnt, d_inode(lower_parent_dentry), lower_dentry, mode); if (err) { @@ -318,7 +327,10 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode } } out: + task_lock(current); current->fs = saved_fs; + task_unlock(current); + free_fs_struct(copied_fs); out_unlock: sdcardfs_put_lower_path(dentry, &lower_path); From 2827d8bc19a36ce9be7af10b7d43211393731007 Mon Sep 17 00:00:00 2001 From: Narender Ankam Date: Thu, 30 Aug 2018 21:45:59 +0530 Subject: [PATCH 44/75] msm: mdss: dsi: fix slab-out-of-bounds issue While handling dsi_gen_read_status, status buffer was xlogging without checking for its max size. Add proper conditional check to xlog status buffer. Change-Id: Ia5a1fe18de123d2911c31ae79492b96f67e1273d Signed-off-by: Narender Ankam --- drivers/video/fbdev/msm/mdss_dsi_panel.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index 5ba0480436a2..bf695ae0beaf 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -1803,17 +1803,13 @@ static bool mdss_dsi_cmp_panel_reg_v2(struct mdss_dsi_ctrl_pdata *ctrl) for (i = 0; i < ctrl->status_cmds.cmd_cnt; i++) len += lenp[i]; - for (i = 0; i < len; i++) { - pr_debug("[%i] return:0x%x status:0x%x\n", - i, (unsigned int)ctrl->return_buf[i], - (unsigned int)ctrl->status_value[j + i]); - MDSS_XLOG(ctrl->ndx, ctrl->return_buf[i], - ctrl->status_value[j + i]); - j += len; - } - for (j = 0; j < ctrl->groups; ++j) { for (i = 0; i < len; ++i) { + pr_debug("[%i] return:0x%x status:0x%x\n", + i, ctrl->return_buf[i], + (unsigned int)ctrl->status_value[group + i]); + MDSS_XLOG(ctrl->ndx, ctrl->return_buf[i], + ctrl->status_value[group + i]); if (ctrl->return_buf[i] != ctrl->status_value[group + i]) break; From eccbac933562a5f95db396d0067385fe0a7c7292 Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Samavedam Date: Tue, 9 Jan 2018 16:40:52 -0800 Subject: [PATCH 45/75] dwc3-msm: Do not resume usb3 phy if max speed is HS only usb3 phy is needed when core is operating at super speed or higher. Do not turn on usb3 phy clocks even when core is programmed to work at high speed only mode. While at it, remove redundant module parameter to control max speed. Speed can be controlled using existing sysfs entry. Example: To set High speed only: echo "high" > /sys/devices/platform/soc//speed To set super speed: echo "super" > /sys/devices/platform/soc//speed Change-Id: I24a9a869d97e6efc3ebc0d7a1374805139c65648 Signed-off-by: Vamsi Krishna Samavedam Signed-off-by: Sriharsha Allenki --- drivers/usb/dwc3/dwc3-msm.c | 48 +++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 920555c64af4..829b3b370fe8 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -239,6 +239,8 @@ struct dwc3_msm { struct delayed_work sdp_check; bool usb_compliance_mode; struct mutex suspend_resume_mutex; + + enum usb_device_speed override_usb_speed; }; #define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */ @@ -1569,8 +1571,17 @@ static void dwc3_restart_usb_work(struct work_struct *w) mdwc->in_restart = false; /* Force reconnect only if cable is still connected */ - if (mdwc->vbus_active) + if (mdwc->vbus_active) { + if (mdwc->override_usb_speed) { + dwc->maximum_speed = mdwc->override_usb_speed; + dwc->gadget.max_speed = dwc->maximum_speed; + dbg_event(0xFF, "override_usb_speed", + mdwc->override_usb_speed); + mdwc->override_usb_speed = 0; + } + dwc3_resume_work(&mdwc->resume_work); + } dwc->err_evt_seen = false; flush_delayed_work(&mdwc->sm_work); @@ -2644,6 +2655,13 @@ static int dwc3_msm_id_notifier(struct notifier_block *nb, if (dwc->maximum_speed > dwc->max_hw_supp_speed) dwc->maximum_speed = dwc->max_hw_supp_speed; + if (!id && mdwc->override_usb_speed) { + dwc->maximum_speed = mdwc->override_usb_speed; + dbg_event(0xFF, "override_usb_speed", + mdwc->override_usb_speed); + mdwc->override_usb_speed = 0; + } + if (mdwc->id_state != id) { mdwc->id_state = id; dbg_event(0xFF, "id_state", mdwc->id_state); @@ -2828,14 +2846,19 @@ static ssize_t mode_store(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR_RW(mode); +/* This node only shows max speed supported dwc3 and it should be + * same as what is reported in udc/core.c max_speed node. For current + * operating gadget speed, query current_speed node which is implemented + * by udc/core.c + */ static ssize_t speed_show(struct device *dev, struct device_attribute *attr, char *buf) { struct dwc3_msm *mdwc = dev_get_drvdata(dev); struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); - return snprintf(buf, PAGE_SIZE, "%s", - usb_speed_string(dwc->max_hw_supp_speed)); + return snprintf(buf, PAGE_SIZE, "%s\n", + usb_speed_string(dwc->maximum_speed)); } static ssize_t speed_store(struct device *dev, struct device_attribute *attr, @@ -2845,14 +2868,25 @@ static ssize_t speed_store(struct device *dev, struct device_attribute *attr, struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); enum usb_device_speed req_speed = USB_SPEED_UNKNOWN; - if (sysfs_streq(buf, "high")) + /* DEVSPD can only have values SS(0x4), HS(0x0) and FS(0x1). + * per 3.20a data book. Allow only these settings. Note that, + * xhci does not support full-speed only mode. + */ + if (sysfs_streq(buf, "full")) + req_speed = USB_SPEED_FULL; + else if (sysfs_streq(buf, "high")) req_speed = USB_SPEED_HIGH; else if (sysfs_streq(buf, "super")) req_speed = USB_SPEED_SUPER; + else + return -EINVAL; - if (req_speed != USB_SPEED_UNKNOWN && - req_speed != dwc->max_hw_supp_speed) { - dwc->maximum_speed = dwc->max_hw_supp_speed = req_speed; + /* restart usb only works for device mode. Perform manual cable + * plug in/out for host mode restart. + */ + if (req_speed != dwc->maximum_speed && + req_speed <= dwc->max_hw_supp_speed) { + mdwc->override_usb_speed = req_speed; schedule_work(&mdwc->restart_usb_work); } From 23db5b808c2449b2193af97b6739e4afea3f1077 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Wed, 21 Nov 2018 17:07:20 -0800 Subject: [PATCH 46/75] usb: gadget: Fix double free of device descriptor pointers Upon driver unbind usb_free_all_descriptors() function frees all speed descriptor pointers without setting them to NULL. In case gadget speed changes (i.e from super speed plus to super speed) after driver unbind only upto super speed descriptor pointers get populated. Super speed plus desc still holds the stale (already freed) pointer. As a result next composition switch results into double free of super speed plus descriptor. Fix this issue by setting all descriptor pointers to NULL after freeing them in usb_free_all_descriptors(). Also clean up gsi_unbind() which is setting up descriptor pointers to NULL already. Change-Id: I4f28294c165bb3b5dc9feb4f22d819f527ad4d50 Signed-off-by: Hemant Kumar Signed-off-by: Sriharsha Allenki --- drivers/usb/gadget/function/f_gsi.c | 11 ++++------- include/linux/usb/gadget.h | 1 + 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index ff61879767b3..266d19049986 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -2843,16 +2843,13 @@ static void gsi_unbind(struct usb_configuration *c, struct usb_function *f) if (gsi->prot_id == IPA_USB_MBIM) mbim_gsi_ext_config_desc.function.subCompatibleID[0] = 0; - if (gadget_is_superspeed(c->cdev->gadget)) { + if (gadget_is_superspeed(c->cdev->gadget)) usb_free_descriptors(f->ss_descriptors); - f->ss_descriptors = NULL; - } - if (gadget_is_dualspeed(c->cdev->gadget)) { + + if (gadget_is_dualspeed(c->cdev->gadget)) usb_free_descriptors(f->hs_descriptors); - f->hs_descriptors = NULL; - } + usb_free_descriptors(f->fs_descriptors); - f->fs_descriptors = NULL; if (gsi->c_port.notify) { kfree(gsi->c_port.notify_req->buf); diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 0e61b1f65359..2bf825f5b711 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -1456,6 +1456,7 @@ struct usb_descriptor_header **usb_copy_descriptors( static inline void usb_free_descriptors(struct usb_descriptor_header **v) { kfree(v); + v = NULL; } struct usb_function; From 9432c10726b8f85a73a7788553943c83affbcb72 Mon Sep 17 00:00:00 2001 From: Monika Singh Date: Thu, 22 Nov 2018 12:18:34 +0530 Subject: [PATCH 47/75] ARM: dts: msm: Remove Out-of-Bound access Remove the out of bound access vulnerability in the qce driver reachable via ioctl. Change-Id: I4320cd27334eaae975f4a6ad07fb7b2e5ebccffd Signed-off-by: Monika Singh --- drivers/crypto/msm/qcedev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c index 953159c66159..425fd6b4b9f5 100644 --- a/drivers/crypto/msm/qcedev.c +++ b/drivers/crypto/msm/qcedev.c @@ -1173,8 +1173,7 @@ static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq, goto exit; } - k_align_dst += creq->vbuf.dst[dst_i].len + - byteoffset; + k_align_dst += creq->vbuf.dst[dst_i].len; creq->data_len -= creq->vbuf.dst[dst_i].len; dst_i++; } else { From 87a0712ca2fdc1a443b25831c6a30dfce0233212 Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Tue, 4 Dec 2018 15:25:39 +0530 Subject: [PATCH 48/75] soc: swr-wcd: Apply div2 setting on slave side before bank switch In soundwire controller, bank switch happen twice for a playback session with stereo speakers. Ensure the setting of div2 applied to inactive bank before bank switch occurs to avoid impact based on bank chosen. Change-Id: I033b19e78309485ca9da85ec67b54409e6fe22cc Signed-off-by: Laxminath Kasam --- drivers/soundwire/swr-wcd-ctrl.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/soundwire/swr-wcd-ctrl.c b/drivers/soundwire/swr-wcd-ctrl.c index a8458b9b6e3a..ce2cc512caa9 100644 --- a/drivers/soundwire/swr-wcd-ctrl.c +++ b/drivers/soundwire/swr-wcd-ctrl.c @@ -653,6 +653,10 @@ static u8 get_inactive_bank_num(struct swr_mstr_ctrl *swrm) static void enable_bank_switch(struct swr_mstr_ctrl *swrm, u8 bank, u8 row, u8 col) { + /* apply div2 setting for inactive bank before bank switch */ + swrm_cmd_fifo_wr_cmd(swrm, 0x01, 0xF, 0x00, + SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(bank)); + swrm_cmd_fifo_wr_cmd(swrm, ((row << 3) | col), 0xF, 0xF, SWRS_SCP_FRAME_CTRL_BANK(bank)); } @@ -891,9 +895,6 @@ static void swrm_apply_port_config(struct swr_master *master) __func__, bank, master->num_port); - swrm_cmd_fifo_wr_cmd(swrm, 0x01, 0xF, 0x00, - SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(bank)); - swrm_copy_data_port_config(master, bank); } From 30d6ebe136dd6ca0a03d6cb7e48179478269a0f9 Mon Sep 17 00:00:00 2001 From: Padmanabhan Komanduru Date: Tue, 13 Nov 2018 15:35:04 +0530 Subject: [PATCH 49/75] msm: mdss: serialize dynamic fps and dynamic bit clock updates Dynamic refresh update and dynamic bit clock switch cannot happen on the same vsync boundary. Serialize them in the commit thread to avoid vsync timeout issues. Change-Id: I55077eca7415bf307ddd30040024b3716a78f6fd Signed-off-by: Padmanabhan Komanduru --- drivers/video/fbdev/msm/mdss_dsi.c | 66 ++++++++++++++++++---- drivers/video/fbdev/msm/mdss_mdp_overlay.c | 7 +++ drivers/video/fbdev/msm/mdss_panel.h | 3 + 3 files changed, 66 insertions(+), 10 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index 69b9149cd750..695db66d8c26 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -2370,6 +2370,49 @@ end_update: return rc; } +static int mdss_dsi_dynamic_bitclk_config(struct mdss_panel_data *pdata) +{ + int rc = 0; + struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; + struct mdss_panel_info *pinfo; + + pr_debug("%s+:\n", __func__); + + if (pdata == NULL) { + pr_err("%s: Invalid input data\n", __func__); + return -EINVAL; + } + + ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, + panel_data); + + if (!ctrl_pdata->panel_data.panel_info.dynamic_bitclk) { + pr_err("Dynamic bitclk not enabled for this panel\n"); + return -EINVAL; + } + + pinfo = &pdata->panel_info; + + if (!pinfo->new_clk_rate || (pinfo->clk_rate == pinfo->new_clk_rate)) { + pr_debug("Bit clock update is not needed\n"); + return 0; + } + + rc = __mdss_dsi_dynamic_clock_switch(&ctrl_pdata->panel_data, + pinfo->new_clk_rate); + if (!rc && mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)) { + struct mdss_dsi_ctrl_pdata *octrl = + mdss_dsi_get_other_ctrl(ctrl_pdata); + rc = __mdss_dsi_dynamic_clock_switch(&octrl->panel_data, + pinfo->new_clk_rate); + if (rc) + pr_err("failed to switch DSI bitclk for sctrl\n"); + } else if (rc) { + pr_err("failed to switch DSI bitclk\n"); + } + return rc; +} + static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) { int rc = 0; @@ -2821,19 +2864,14 @@ static ssize_t dynamic_bitclk_sysfs_wta(struct device *dev, return -EINVAL; } - rc = __mdss_dsi_dynamic_clock_switch(&ctrl_pdata->panel_data, - clk_rate); - if (!rc && mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)) { + pinfo->new_clk_rate = clk_rate; + if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)) { struct mdss_dsi_ctrl_pdata *octrl = mdss_dsi_get_other_ctrl(ctrl_pdata); - rc = __mdss_dsi_dynamic_clock_switch(&octrl->panel_data, - clk_rate); - if (rc) - pr_err("failed to switch DSI bitclk for sctrl\n"); - } else if (rc) { - pr_err("failed to switch DSI bitclk\n"); - } + struct mdss_panel_info *opinfo = &octrl->panel_data.panel_info; + opinfo->new_clk_rate = clk_rate; + } return count; } /* dynamic_bitclk_sysfs_wta */ @@ -3061,6 +3099,14 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, case MDSS_EVENT_AVR_MODE: mdss_dsi_avr_config(ctrl_pdata, (int)(unsigned long) arg); break; + case MDSS_EVENT_DSI_DYNAMIC_BITCLK: + if (ctrl_pdata->panel_data.panel_info.dynamic_bitclk) { + rc = mdss_dsi_dynamic_bitclk_config(pdata); + if (rc) + pr_err("unable to change bitclk error-%d\n", + rc); + } + break; default: pr_debug("%s: unhandled event=%d\n", __func__, event); break; diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 34001ab35e55..48422fcf0139 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -2659,6 +2659,13 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, goto commit_fail; } + ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_DSI_DYNAMIC_BITCLK, + NULL, CTL_INTF_EVENT_FLAG_SKIP_BROADCAST); + if (IS_ERR_VALUE(ret)) { + pr_err("failed to update dynamic bit clk!\n"); + goto commit_fail; + } + mutex_lock(&mdp5_data->ov_lock); /* Disable secure display/camera for video mode panels */ diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index de3ff0c77625..f8993f3774e6 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -308,6 +308,7 @@ enum mdss_intf_events { MDSS_EVENT_DSI_TIMING_DB_CTRL, MDSS_EVENT_AVR_MODE, MDSS_EVENT_REGISTER_CLAMP_HANDLER, + MDSS_EVENT_DSI_DYNAMIC_BITCLK, MDSS_EVENT_MAX, }; @@ -814,6 +815,8 @@ struct mdss_panel_info { bool esd_check_enabled; bool allow_phy_power_off; char dfps_update; + /* new requested bitclk before it is updated in hw */ + int new_clk_rate; /* new requested fps before it is updated in hw */ int new_fps; /* stores initial fps after boot */ From 34e75f5628e6676eb1db3a75254565ea109162a9 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Tue, 21 Nov 2017 10:11:34 -0800 Subject: [PATCH 50/75] msm: ipa3: fix holb sequence for SSR The correct sequence for enabling HOLB drop is first to suspend the pipe and then to HOLB drop. Change-Id: I78b7b268eec230a4993e446bd90846f800364e06 CRs-Fixed: 2141518 Acked-by: Ady Abraham Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/ipa.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index dfff3b422659..60b003033ef5 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -2162,6 +2162,12 @@ static void ipa3_q6_avoid_holb(void) if (ep_idx == -1) continue; + /* from IPA 4.0 pipe suspend is not supported */ + if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) + ipahal_write_reg_n_fields( + IPA_ENDP_INIT_CTRL_n, + ep_idx, &ep_suspend); + /* * ipa3_cfg_ep_holb is not used here because we are * setting HOLB on Q6 pipes, and from APPS perspective @@ -2174,10 +2180,6 @@ static void ipa3_q6_avoid_holb(void) ipahal_write_reg_n_fields( IPA_ENDP_INIT_HOL_BLOCK_EN_n, ep_idx, &ep_holb); - - ipahal_write_reg_n_fields( - IPA_ENDP_INIT_CTRL_n, - ep_idx, &ep_suspend); } } } From 5bf83ce8c3f95be88cb8f16324b5863ffc5d5697 Mon Sep 17 00:00:00 2001 From: Meera Gande Date: Thu, 11 Oct 2018 15:32:51 +0530 Subject: [PATCH 51/75] msm: camera: isp: Handle frame drop due to delay In few scenarios, the request frame may get delayed and current and request frame id may become same. To handle such scenarios, made changes to inform user to delay a frame and process the request. Change-Id: I31fa04c386922c48a043c511a163c76316e21987 Signed-off-by: Meera Gande --- .../platform/msm/camera_v2/isp/msm_isp.c | 4 ++-- .../platform/msm/camera_v2/isp/msm_isp.h | 7 +----- .../msm/camera_v2/isp/msm_isp_axi_util.c | 23 ++++++++++++++++--- include/uapi/media/msmb_isp.h | 7 ++++++ 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c index 18961e69aadc..fa5aee08c37d 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c @@ -467,7 +467,7 @@ static int isp_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct page *page; struct vfe_device *vfe_dev = vma->vm_private_data; - struct isp_proc *isp_page = NULL; + struct isp_kstate *isp_page = NULL; isp_page = vfe_dev->isp_page; @@ -749,7 +749,7 @@ int vfe_hw_probe(struct platform_device *pdev) vfe_dev->buf_mgr->init_done = 1; vfe_dev->vfe_open_cnt = 0; /*Allocate a page in kernel and map it to camera user process*/ - vfe_dev->isp_page = (struct isp_proc *)get_zeroed_page(GFP_KERNEL); + vfe_dev->isp_page = (struct isp_kstate *)get_zeroed_page(GFP_KERNEL); if (vfe_dev->isp_page == NULL) { pr_err("%s: no enough memory\n", __func__); rc = -ENOMEM; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h index da8fbb3cd5b9..0c18bfe55842 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h @@ -762,11 +762,6 @@ struct msm_vfe_common_subdev { struct msm_vfe_common_dev_data *common_data; }; -struct isp_proc { - uint32_t kernel_sofid; - uint32_t vfeid; -}; - struct vfe_device { /* Driver private data */ struct platform_device *pdev; @@ -851,7 +846,7 @@ struct vfe_device { uint32_t recovery_irq1_mask; /* total bandwidth per vfe */ uint64_t total_bandwidth; - struct isp_proc *isp_page; + struct isp_kstate *isp_page; }; struct vfe_parent_device { diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index 661850d6d7c6..180e5df98cc6 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -3497,6 +3497,14 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev, frame_src = SRC_TO_INTF(stream_info->stream_src); pingpong_status = vfe_dev->hw_info-> vfe_ops.axi_ops.get_pingpong_status(vfe_dev); + + /* As MCT is still processing it, need to drop the additional requests*/ + if (vfe_dev->isp_page->drop_reconfig) { + pr_err("%s: MCT has not yet delayed %d drop request %d\n", + __func__, vfe_dev->isp_page->drop_reconfig, frame_id); + goto error; + } + /* * If PIX stream is active then RDI path uses SOF frame ID of PIX * In case of standalone RDI streaming, SOF are used from @@ -3510,9 +3518,18 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev, vfe_dev->axi_data.src_info[frame_src].accept_frame == false) { pr_debug("%s:%d invalid time to request frame %d\n", __func__, __LINE__, frame_id); - goto error; - } - if ((vfe_dev->axi_data.src_info[frame_src].active && (frame_id != + vfe_dev->isp_page->drop_reconfig = 1; + } else if ((vfe_dev->axi_data.src_info[frame_src].active) && + (frame_id == + vfe_dev->axi_data.src_info[frame_src].frame_id) && + (stream_info->undelivered_request_cnt <= + MAX_BUFFERS_IN_HW)) { + vfe_dev->isp_page->drop_reconfig = 1; + pr_debug("%s: vfe_%d request_frame %d cur frame id %d pix %d\n", + __func__, vfe_dev->pdev->id, frame_id, + vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id, + vfe_dev->axi_data.src_info[VFE_PIX_0].active); + } else if ((vfe_dev->axi_data.src_info[frame_src].active && (frame_id != vfe_dev->axi_data.src_info[frame_src].frame_id + vfe_dev-> axi_data.src_info[frame_src].sof_counter_step)) || ((!vfe_dev->axi_data.src_info[frame_src].active))) { diff --git a/include/uapi/media/msmb_isp.h b/include/uapi/media/msmb_isp.h index d84bb30d56fa..40e5c273011f 100644 --- a/include/uapi/media/msmb_isp.h +++ b/include/uapi/media/msmb_isp.h @@ -25,9 +25,16 @@ #define ISP_STATS_STREAM_BIT 0x80000000 #define VFE_HW_LIMIT 1 +#define ISP_KERNEL_STATE 1 struct msm_vfe_cfg_cmd_list; +struct isp_kstate { + uint32_t kernel_sofid; + uint32_t drop_reconfig; + uint32_t vfeid; +}; + enum ISP_START_PIXEL_PATTERN { ISP_BAYER_RGRGRG, ISP_BAYER_GRGRGR, From 8d4b7f9a0e0b22b4f288c8d1d3b5cb60c5165350 Mon Sep 17 00:00:00 2001 From: Meera Gande Date: Thu, 25 Oct 2018 11:35:12 +0530 Subject: [PATCH 52/75] msm: camera: isp: Fix drop frame due to reg update miss In few scenarios, where the register update ioctl is missed, the handling of frame drop is not working in such scenarios as the frame drop pattern is not set correctly. Once the epoch handling is done, we need to re-configure the buffer and pattern. Change-Id: I87b2cecda7e7e1addc68511dad6a80498051f87a Signed-off-by: Meera Gande --- drivers/media/platform/msm/camera_v2/isp/msm_isp40.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c index f4e4ca6cb6dc..1445943fd275 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c @@ -752,13 +752,13 @@ static void msm_vfe40_process_epoch_irq(struct vfe_device *vfe_dev, return; if (irq_status0 & BIT(2)) { - msm_isp_notify(vfe_dev, ISP_EVENT_SOF, VFE_PIX_0, ts); ISP_DBG("%s: EPOCH0 IRQ\n", __func__); msm_isp_process_reg_upd_epoch_irq(vfe_dev, VFE_PIX_0, MSM_ISP_COMP_IRQ_EPOCH, ts); msm_isp_process_stats_reg_upd_epoch_irq(vfe_dev, MSM_ISP_COMP_IRQ_EPOCH); msm_isp_update_error_frame_count(vfe_dev); + msm_isp_notify(vfe_dev, ISP_EVENT_SOF, VFE_PIX_0, ts); if (vfe_dev->axi_data.src_info[VFE_PIX_0].raw_stream_count > 0 && vfe_dev->axi_data.src_info[VFE_PIX_0]. stream_count == 0) { From 475b454dd2b610b139d6f481d985da0fb99b2830 Mon Sep 17 00:00:00 2001 From: Meera Gande Date: Wed, 10 Oct 2018 15:56:54 +0530 Subject: [PATCH 53/75] msm: camera: isp: Reset request queue at stop In few scenarios where the buffers are not queued from HAL, request queue overflow is seen. Added changes to reset the queue at destroy and when the buffer is not available to process. Change-Id: I7239175dda9cbc26fb65f568cbc5f7183ceaa24d Signed-off-by: Meera Gande --- .../media/platform/msm/camera_v2/isp/msm_isp_axi_util.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index 661850d6d7c6..40ece2ffcf4b 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -172,6 +172,8 @@ static void msm_isp_axi_destroy_stream( stream_info->bufq_handle[k] = 0; stream_info->vfe_mask = 0; stream_info->state = AVAILABLE; + memset(&stream_info->request_queue_cmd, + 0, sizeof(stream_info->request_queue_cmd)); } } @@ -3617,6 +3619,9 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev, stream_info->undelivered_request_cnt--; pr_err_ratelimited("%s:%d fail to cfg HAL buffer\n", __func__, __LINE__); + queue_req->cmd_used = 0; + list_del(&queue_req->list); + stream_info->request_q_cnt--; return rc; } @@ -3655,6 +3660,9 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev, flags); pr_err_ratelimited("%s:%d fail to cfg HAL buffer\n", __func__, __LINE__); + queue_req->cmd_used = 0; + list_del(&queue_req->list); + stream_info->request_q_cnt--; return rc; } } else { From 7f1241f1882ce796b72c969e8a9a4327ac9b4874 Mon Sep 17 00:00:00 2001 From: Teng Fei Fan Date: Fri, 28 Sep 2018 15:47:30 +0800 Subject: [PATCH 54/75] ARM: dts: msm: Add initial dts support for SDM455 RCM devices Add initial device trees for SDM455 RCM devices for both external and internal codec variant. Change-Id: Idd6034727acc8b9ef600da421963becf5f2305cd Signed-off-by: Teng Fei Fan Signed-off-by: Maria Yu Signed-off-by: Tengfei Fan --- arch/arm/boot/dts/qcom/Makefile | 4 ++- .../dts/qcom/sdm455-internal-codec-rcm.dts | 24 +++++++++++++ arch/arm/boot/dts/qcom/sdm455-rcm.dts | 34 +++++++++++++++++++ arch/arm/boot/dts/qcom/sdm455-rcm.dtsi | 13 +++++++ 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/qcom/sdm455-internal-codec-rcm.dts create mode 100644 arch/arm/boot/dts/qcom/sdm455-rcm.dts create mode 100644 arch/arm/boot/dts/qcom/sdm455-rcm.dtsi diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index 0bd48399205b..c56b1c2be598 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -292,7 +292,9 @@ dtb-$(CONFIG_ARCH_SDM630) += sdm630-rumi.dtb \ sdm630-pm660a-headset-jacktype-no-rcm.dtb \ sdm455-mtp.dtb \ sdm455-qrd.dtb \ - sdm455-cdp.dtb + sdm455-cdp.dtb \ + sdm455-rcm.dtb \ + sdm455-internal-codec-rcm.dtb ifeq ($(CONFIG_ARM64),y) always := $(dtb-y) diff --git a/arch/arm/boot/dts/qcom/sdm455-internal-codec-rcm.dts b/arch/arm/boot/dts/qcom/sdm455-internal-codec-rcm.dts new file mode 100644 index 000000000000..a43de6111483 --- /dev/null +++ b/arch/arm/boot/dts/qcom/sdm455-internal-codec-rcm.dts @@ -0,0 +1,24 @@ +/* Copyright (c) 2018, 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. + */ + + +/dts-v1/; + +#include "sdm455.dtsi" +#include "sdm455-rcm.dtsi" +#include "sdm660-internal-codec.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SDM455 Int. Audio Codec RCM"; + compatible = "qcom,sdm630-cdp", "qcom,sdm630", "qcom,cdp"; + qcom,board-id = <21 1>; +}; diff --git a/arch/arm/boot/dts/qcom/sdm455-rcm.dts b/arch/arm/boot/dts/qcom/sdm455-rcm.dts new file mode 100644 index 000000000000..868f8b940737 --- /dev/null +++ b/arch/arm/boot/dts/qcom/sdm455-rcm.dts @@ -0,0 +1,34 @@ +/* Copyright (c) 2018, 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. + */ + + +/dts-v1/; + +#include "sdm455.dtsi" +#include "sdm455-rcm.dtsi" +#include "sdm660-external-codec.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SDM 630 PM660 + PM660L RCM"; + compatible = "qcom,sdm630-cdp", "qcom,sdm630", "qcom,cdp"; + qcom,board-id = <21 0>; +}; + +&tavil_snd { + qcom,msm-mbhc-hphl-swh = <0>; + qcom,msm-mbhc-gnd-swh = <0>; +}; + +&tasha_snd { + qcom,msm-mbhc-hphl-swh = <0>; + qcom,msm-mbhc-gnd-swh = <0>; +}; diff --git a/arch/arm/boot/dts/qcom/sdm455-rcm.dtsi b/arch/arm/boot/dts/qcom/sdm455-rcm.dtsi new file mode 100644 index 000000000000..bc54d29450e1 --- /dev/null +++ b/arch/arm/boot/dts/qcom/sdm455-rcm.dtsi @@ -0,0 +1,13 @@ +/* Copyright (c) 2018, 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. + */ + +#include "sdm630-cdp.dtsi" From c3852a5d61919f8432d3314f989913c8bcbf2cd8 Mon Sep 17 00:00:00 2001 From: Hardik Arya Date: Fri, 23 Nov 2018 10:41:41 +0530 Subject: [PATCH 55/75] diag: Mark Buffer as NULL after freeing There is a possibility of use-after-free and double free because of not marking buffer as NULL after freeing. The patch marks buffer as NULL after freeing in error case. Change-Id: Iacf8f8a4a4e644f48c87d5445ccd594766f2e156 Signed-off-by: Hardik Arya --- drivers/char/diag/diag_masks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c index 6e828bca64aa..bb28958412ed 100644 --- a/drivers/char/diag/diag_masks.c +++ b/drivers/char/diag/diag_masks.c @@ -1748,6 +1748,7 @@ static int __diag_mask_init(struct diag_mask_info *mask_info, int mask_len, mask_info->update_buf = kzalloc(update_buf_len, GFP_KERNEL); if (!mask_info->update_buf) { kfree(mask_info->ptr); + mask_info->ptr = NULL; return -ENOMEM; } kmemleak_not_leak(mask_info->update_buf); From a72d8d872dababf0e59177229a19ab1d71946f1d Mon Sep 17 00:00:00 2001 From: Amine Najahi Date: Tue, 18 Sep 2018 14:41:49 -0400 Subject: [PATCH 56/75] drm/msm/sde: sanitize debugfs inputs when reading mdp memory Sanitize debugfs inputs to only allow access to mdp memory block specified in dtsi file. This change will allow only one single block to be read at the time and will avoid accessing memory outside of valid decode space which can trigger AHB error bus response. Change-Id: I91b91ac2b31eac4facb0c402c92ed8fcfc01d91e Signed-off-by: Amine Najahi --- drivers/gpu/drm/msm/sde_dbg.c | 42 +++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/sde_dbg.c b/drivers/gpu/drm/msm/sde_dbg.c index 93c4c1e27b0d..50c0787d794d 100644 --- a/drivers/gpu/drm/msm/sde_dbg.c +++ b/drivers/gpu/drm/msm/sde_dbg.c @@ -1897,6 +1897,37 @@ static int sde_dbg_reg_base_release(struct inode *inode, struct file *file) return 0; } +/** + * sde_dbg_reg_base_is_valid_range - verify if requested memory range is valid + * @off: address offset in bytes + * @cnt: memory size in bytes + * Return: true if valid; false otherwise + */ +static bool sde_dbg_reg_base_is_valid_range(u32 off, u32 cnt) +{ + static struct sde_dbg_base *dbg_base = &sde_dbg_base; + struct sde_dbg_reg_range *node; + struct sde_dbg_reg_base *base; + + pr_debug("check offset=0x%x cnt=0x%x\n", off, cnt); + + list_for_each_entry(base, &dbg_base->reg_base_list, reg_base_head) { + list_for_each_entry(node, &base->sub_range_list, head) { + pr_debug("%s: start=0x%x end=0x%x\n", node->range_name, + node->offset.start, node->offset.end); + + if (node->offset.start <= off + && off <= node->offset.end + && off + cnt <= node->offset.end) { + pr_debug("valid range requested\n"); + return true; + } + } + } + + pr_err("invalid range requested\n"); + return false; +} /** * sde_dbg_reg_base_offset_write - set new offset and len to debugfs reg base @@ -1951,8 +1982,15 @@ static ssize_t sde_dbg_reg_base_offset_write(struct file *file, goto exit; } - if (cnt == 0) - return -EINVAL; + if (cnt == 0) { + rc = -EINVAL; + goto exit; + } + + if (!sde_dbg_reg_base_is_valid_range(off, cnt)) { + rc = -EINVAL; + goto exit; + } dbg->off = off; dbg->cnt = cnt; From f4cc27b8cdbfab08f9907cf26f7f97f8fd456ea6 Mon Sep 17 00:00:00 2001 From: E V Ravi Date: Tue, 18 Dec 2018 14:41:59 +0530 Subject: [PATCH 57/75] msm: ais: Fix for OOB security CR If the user passes the arbitrary command with _IOC_DIR(cmd) == _IOC_NONE, "arg" should point to any arbitrary address. Check for invalid command and return error. CRs-Fixed: 2299567 Change-Id: Ibd77adfe53ef0777ff4eb96c914e21f43dfd6749 Signed-off-by: E V Ravi --- .../media/platform/msm/ais/sensor/ir_led/msm_ir_led.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/msm/ais/sensor/ir_led/msm_ir_led.c b/drivers/media/platform/msm/ais/sensor/ir_led/msm_ir_led.c index 9e200071f9eb..1492d19d21d6 100644 --- a/drivers/media/platform/msm/ais/sensor/ir_led/msm_ir_led.c +++ b/drivers/media/platform/msm/ais/sensor/ir_led/msm_ir_led.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, 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 @@ -312,10 +312,6 @@ static long msm_ir_led_subdev_do_ioctl( (struct msm_ir_led_cfg_data_t32 *)arg; struct msm_ir_led_cfg_data_t ir_led_data; - ir_led_data.cfg_type = u32->cfg_type; - ir_led_data.pwm_duty_on_ns = u32->pwm_duty_on_ns; - ir_led_data.pwm_period_ns = u32->pwm_period_ns; - switch (cmd) { case VIDIOC_MSM_IR_LED_CFG32: cmd = VIDIOC_MSM_IR_LED_CFG; @@ -324,6 +320,10 @@ static long msm_ir_led_subdev_do_ioctl( return msm_ir_led_subdev_ioctl(sd, cmd, arg); } + ir_led_data.cfg_type = u32->cfg_type; + ir_led_data.pwm_duty_on_ns = u32->pwm_duty_on_ns; + ir_led_data.pwm_period_ns = u32->pwm_period_ns; + rc = msm_ir_led_subdev_ioctl(sd, cmd, &ir_led_data); return rc; From 6a3cde9d1725e899c7f44cf09cfe51b5770d7bb1 Mon Sep 17 00:00:00 2001 From: Abhishek Abbanaveni Date: Tue, 20 Nov 2018 14:38:02 +0530 Subject: [PATCH 58/75] msm: camera: Fix invalid type conversion Invalid type conversion with x64 bit command VIDIOC_MSM_LASER_LED_CFG passed in,for which the type should be "msm_laser_led_cfg_data_t" Change-Id: I43e112224c612fb5390fa5fc23e8ae9c0e553288 CRs-Fixed: 2299699 Signed-off-by: Abhishek Abbanaveni Signed-off-by: E V Ravi --- .../sensor/laser_led/msm_laser_led.c | 67 ++++++++++++++++--- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/sensor/laser_led/msm_laser_led.c b/drivers/media/platform/msm/camera_v2/sensor/laser_led/msm_laser_led.c index c368f081f97b..68d3c71601eb 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/laser_led/msm_laser_led.c +++ b/drivers/media/platform/msm/camera_v2/sensor/laser_led/msm_laser_led.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, 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 @@ -70,18 +70,15 @@ static struct msm_camera_i2c_fn_t msm_sensor_cci_func_tbl = { .i2c_util = msm_sensor_cci_i2c_util, .i2c_poll = msm_camera_cci_i2c_poll, }; -#ifdef CONFIG_COMPAT + static int32_t msm_laser_led_init( struct msm_laser_led_ctrl_t *laser_led_ctrl, - struct msm_laser_led_cfg_data_t32 __user *laser_led_data) -#else -static int32_t msm_laser_led_init( - struct msm_laser_led_ctrl_t *laser_led_ctrl, - struct msm_laser_led_cfg_data_t __user *laser_led_data) -#endif + void __user *argp) { int32_t rc = -EFAULT; struct msm_camera_cci_client *cci_client = NULL; + struct msm_laser_led_cfg_data_t __user *laser_led_data = + (struct msm_laser_led_cfg_data_t __user *) argp; CDBG("Enter\n"); @@ -263,6 +260,53 @@ static int32_t msm_laser_led_control32( return rc; } + +static int32_t msm_laser_led_init32( + struct msm_laser_led_ctrl_t *laser_led_ctrl, + void __user *argp) +{ + int32_t rc = -EFAULT; + struct msm_laser_led_cfg_data_t32 __user *laser_led_data = + (struct msm_laser_led_cfg_data_t32 __user *) argp; + struct msm_camera_cci_client *cci_client = NULL; + + CDBG("Enter\n"); + + if (laser_led_ctrl->laser_led_state == MSM_CAMERA_LASER_LED_INIT) { + pr_err("Invalid laser_led state = %d\n", + laser_led_ctrl->laser_led_state); + return 0; + } + + rc = laser_led_ctrl->i2c_client.i2c_func_tbl->i2c_util( + &laser_led_ctrl->i2c_client, MSM_CCI_INIT); + if (rc < 0) + pr_err("cci_init failed\n"); + + cci_client = laser_led_ctrl->i2c_client.cci_client; + + if (copy_from_user(&(cci_client->sid), + &(laser_led_data->i2c_addr), + sizeof(uint16_t))) { + pr_err("%s:%d failed\n", __func__, __LINE__); + return -EFAULT; + } + cci_client->sid = cci_client->sid >> 1; + cci_client->retries = 3; + cci_client->id_map = 0; + + if (copy_from_user(&(cci_client->i2c_freq_mode), + &(laser_led_data->i2c_freq_mode), + sizeof(enum i2c_freq_mode_t))) { + pr_err("%s:%d failed\n", __func__, __LINE__); + return -EFAULT; + } + + laser_led_ctrl->laser_led_state = MSM_CAMERA_LASER_LED_INIT; + + CDBG("Exit\n"); + return 0; +} #endif static int32_t msm_laser_led_control( @@ -381,7 +425,12 @@ static int32_t msm_laser_led_config(struct msm_laser_led_ctrl_t *laser_led_ctrl, switch (cfg_type) { case CFG_LASER_LED_INIT: - rc = msm_laser_led_init(laser_led_ctrl, laser_led_data); +#ifdef CONFIG_COMPAT + if (is_compat_task()) + rc = msm_laser_led_init32(laser_led_ctrl, argp); + else +#endif + rc = msm_laser_led_init(laser_led_ctrl, argp); break; case CFG_LASER_LED_CONTROL: #ifdef CONFIG_COMPAT From bb6a5a514840d6eec546903358a635c1263d9bf4 Mon Sep 17 00:00:00 2001 From: Abhishek Abbanaveni Date: Tue, 20 Nov 2018 14:57:06 +0530 Subject: [PATCH 59/75] msm: camera: Fix for OOB security CR If user passes an aribitary command with _IOC_DIR(cmd) == _IOC_NONE, "arg" should point to any arbitrary address. Check for invalid command and return error. Change-Id: If60191a07bb80939af2d471a5acf1b17dd68aa58 CRs-Fixed: 2299567 Signed-off-by: Abhishek Abbanaveni --- .../platform/msm/camera_v2/sensor/ir_led/msm_ir_led.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/sensor/ir_led/msm_ir_led.c b/drivers/media/platform/msm/camera_v2/sensor/ir_led/msm_ir_led.c index 9af7abc5cd04..e4d095d1a882 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/ir_led/msm_ir_led.c +++ b/drivers/media/platform/msm/camera_v2/sensor/ir_led/msm_ir_led.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018 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 @@ -324,10 +324,6 @@ static long msm_ir_led_subdev_do_ioctl( struct msm_ir_led_cfg_data_t ir_led_data; CDBG("Enter\n"); - ir_led_data.cfg_type = u32->cfg_type; - ir_led_data.pwm_duty_on_ns = u32->pwm_duty_on_ns; - ir_led_data.pwm_period_ns = u32->pwm_period_ns; - switch (cmd) { case VIDIOC_MSM_IR_LED_CFG32: cmd = VIDIOC_MSM_IR_LED_CFG; @@ -336,6 +332,10 @@ static long msm_ir_led_subdev_do_ioctl( return msm_ir_led_subdev_ioctl(sd, cmd, arg); } + ir_led_data.cfg_type = u32->cfg_type; + ir_led_data.pwm_duty_on_ns = u32->pwm_duty_on_ns; + ir_led_data.pwm_period_ns = u32->pwm_period_ns; + rc = msm_ir_led_subdev_ioctl(sd, cmd, &ir_led_data); CDBG("Exit\n"); From 3a1e5f4ce9ee00f63ab27aeb92b64a579b4aa4f2 Mon Sep 17 00:00:00 2001 From: Abhishek Abbanaveni Date: Tue, 20 Nov 2018 14:57:06 +0530 Subject: [PATCH 60/75] msm: camera: Fix for OOB security CR If user passes an aribitary command with _IOC_DIR(cmd) == _IOC_NONE, "arg" should point to any arbitrary address. Check for invalid command and return error. Change-Id: If60191a07bb80939af2d471a5acf1b17dd68aa58 CRs-Fixed: 2299567 Signed-off-by: Abhishek Abbanaveni --- .../platform/msm/camera_v2/sensor/ir_led/msm_ir_led.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/sensor/ir_led/msm_ir_led.c b/drivers/media/platform/msm/camera_v2/sensor/ir_led/msm_ir_led.c index 9af7abc5cd04..e4d095d1a882 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/ir_led/msm_ir_led.c +++ b/drivers/media/platform/msm/camera_v2/sensor/ir_led/msm_ir_led.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018 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 @@ -324,10 +324,6 @@ static long msm_ir_led_subdev_do_ioctl( struct msm_ir_led_cfg_data_t ir_led_data; CDBG("Enter\n"); - ir_led_data.cfg_type = u32->cfg_type; - ir_led_data.pwm_duty_on_ns = u32->pwm_duty_on_ns; - ir_led_data.pwm_period_ns = u32->pwm_period_ns; - switch (cmd) { case VIDIOC_MSM_IR_LED_CFG32: cmd = VIDIOC_MSM_IR_LED_CFG; @@ -336,6 +332,10 @@ static long msm_ir_led_subdev_do_ioctl( return msm_ir_led_subdev_ioctl(sd, cmd, arg); } + ir_led_data.cfg_type = u32->cfg_type; + ir_led_data.pwm_duty_on_ns = u32->pwm_duty_on_ns; + ir_led_data.pwm_period_ns = u32->pwm_period_ns; + rc = msm_ir_led_subdev_ioctl(sd, cmd, &ir_led_data); CDBG("Exit\n"); From 19194c8ef8115cdc20ceefd921c874799332a754 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Thu, 23 Aug 2018 05:00:05 +0530 Subject: [PATCH 61/75] msm: adsprpc: allocate all remote memory in kernel Allocate all memory given to remote subsystem in the kernel instead of mapping memory allocated in userspace. Change-Id: I79c1f40d426e271403afa67514714fe6af26cf4e Acked-by: Thyagarajan Venkatanarayanan Signed-off-by: Tharun Kumar Merugu --- drivers/char/adsprpc.c | 398 +++++++++++++++++++++++++--------- drivers/char/adsprpc_compat.c | 55 +++++ drivers/char/adsprpc_shared.h | 29 ++- 3 files changed, 374 insertions(+), 108 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 24513e5d1e1e..3da8f64444a3 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -55,6 +55,8 @@ #define TZ_PIL_AUTH_QDSP6_PROC 1 #define ADSP_MMAP_HEAP_ADDR 4 #define ADSP_MMAP_REMOTE_HEAP_ADDR 8 +#define ADSP_MMAP_ADD_PAGES 0x1000 + #define FASTRPC_ENOSUCH 39 #define VMID_SSC_Q6 38 #define VMID_ADSP_Q6 6 @@ -126,6 +128,7 @@ static inline uint64_t buf_num_pages(uint64_t buf, size_t len) static inline uint64_t buf_page_size(uint32_t size) { uint64_t sz = (size + (PAGE_SIZE - 1)) & PAGE_MASK; + return sz > PAGE_SIZE ? sz : PAGE_SIZE; } @@ -145,10 +148,15 @@ struct fastrpc_file; struct fastrpc_buf { struct hlist_node hn; + struct hlist_node hn_rem; struct fastrpc_file *fl; void *virt; uint64_t phys; size_t size; + struct dma_attrs attrs; + uintptr_t raddr; + uint32_t flags; + int remote; }; struct fastrpc_ctx_lst; @@ -292,9 +300,11 @@ struct fastrpc_file { struct hlist_node hn; spinlock_t hlock; struct hlist_head maps; - struct hlist_head bufs; + struct hlist_head cached_bufs; + struct hlist_head remote_bufs; struct fastrpc_ctx_lst clst; struct fastrpc_session_ctx *sctx; + struct fastrpc_buf *init_mem; struct fastrpc_session_ctx *secsctx; uint32_t mode; uint32_t profile; @@ -363,10 +373,17 @@ static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache) return; if (cache) { spin_lock(&fl->hlock); - hlist_add_head(&buf->hn, &fl->bufs); + hlist_add_head(&buf->hn, &fl->cached_bufs); spin_unlock(&fl->hlock); return; } + if (buf->remote) { + spin_lock(&fl->hlock); + hlist_del_init(&buf->hn_rem); + spin_unlock(&fl->hlock); + buf->remote = 0; + buf->raddr = 0; + } if (!IS_ERR_OR_NULL(buf->virt)) { int destVM[1] = {VMID_HLOS}; int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; @@ -380,21 +397,22 @@ static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache) hyp_assign_phys(buf->phys, buf_page_size(buf->size), srcVM, 2, destVM, destVMperm, 1); } - dma_free_coherent(fl->sctx->smmu.dev, buf->size, buf->virt, - buf->phys); + dma_free_attrs(fl->sctx->smmu.dev, buf->size, buf->virt, + buf->phys, (struct dma_attrs *)&buf->attrs); } kfree(buf); } -static void fastrpc_buf_list_free(struct fastrpc_file *fl) +static void fastrpc_cached_buf_list_free(struct fastrpc_file *fl) { struct fastrpc_buf *buf, *free; + do { struct hlist_node *n; free = NULL; spin_lock(&fl->hlock); - hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) { + hlist_for_each_entry_safe(buf, n, &fl->cached_bufs, hn) { hlist_del_init(&buf->hn); free = buf; break; @@ -405,6 +423,25 @@ static void fastrpc_buf_list_free(struct fastrpc_file *fl) } while (free); } +static void fastrpc_remote_buf_list_free(struct fastrpc_file *fl) +{ + struct fastrpc_buf *buf, *free; + + do { + struct hlist_node *n; + + free = NULL; + spin_lock(&fl->hlock); + hlist_for_each_entry_safe(buf, n, &fl->remote_bufs, hn_rem) { + free = buf; + break; + } + spin_unlock(&fl->hlock); + if (free) + fastrpc_buf_free(free, 0); + } while (free); +} + static void fastrpc_mmap_add(struct fastrpc_mmap *map) { if (map->flags == ADSP_MMAP_HEAP_ADDR || @@ -465,23 +502,21 @@ static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd, uintptr_t va, return -ENOTTY; } -static int dma_alloc_memory(phys_addr_t *region_start, size_t size) +static int dma_alloc_memory(dma_addr_t *region_start, void **vaddr, size_t size, + struct dma_attrs *attrs) { struct fastrpc_apps *me = &gfa; - void *vaddr = NULL; - DEFINE_DMA_ATTRS(attrs); if (me->dev == NULL) { pr_err("device adsprpc-mem is not initialized\n"); return -ENODEV; } - dma_set_attr(DMA_ATTR_SKIP_ZEROING, &attrs); - dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); - vaddr = dma_alloc_attrs(me->dev, size, region_start, GFP_KERNEL, - &attrs); - if (!vaddr) { - pr_err("ADSPRPC: Failed to allocate %x remote heap memory\n", - (unsigned int)size); + + *vaddr = dma_alloc_attrs(me->dev, size, region_start, + GFP_KERNEL, attrs); + if (IS_ERR_OR_NULL(*vaddr)) { + pr_err("adsprpc: %s: %s: dma_alloc_attrs failed for size 0x%zx, returned %pK\n", + current->comm, __func__, size, (*vaddr)); return -ENOMEM; } return 0; @@ -617,7 +652,8 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, unsigned attr, struct fastrpc_channel_ctx *chan = &apps->channel[cid]; struct fastrpc_mmap *map = NULL; struct dma_attrs attrs; - phys_addr_t region_start = 0; + dma_addr_t region_start = 0; + void *region_vaddr = NULL; unsigned long flags; int err = 0, vmid; @@ -635,14 +671,20 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, unsigned attr, map->attr = attr; if (mflags == ADSP_MMAP_HEAP_ADDR || mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + DEFINE_DMA_ATTRS(rh_attrs); + + dma_set_attr(DMA_ATTR_SKIP_ZEROING, &rh_attrs); + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &rh_attrs); + map->apps = me; map->fl = NULL; - VERIFY(err, !dma_alloc_memory(®ion_start, len)); + VERIFY(err, !dma_alloc_memory(®ion_start, + ®ion_vaddr, len, &rh_attrs)); if (err) goto bail; map->phys = (uintptr_t)region_start; map->size = len; - map->va = (uintptr_t)map->phys; + map->va = (uintptr_t)region_vaddr; } else { VERIFY(err, !IS_ERR_OR_NULL(map->handle = ion_import_dma_buf(fl->apps->client, fd))); @@ -741,7 +783,8 @@ bail: } static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, - struct fastrpc_buf **obuf) + struct dma_attrs attr, uint32_t rflags, + int remote, struct fastrpc_buf **obuf) { int err = 0, vmid; struct fastrpc_buf *buf = NULL, *fr = NULL; @@ -751,18 +794,20 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, if (err) goto bail; - /* find the smallest buffer that fits in the cache */ - spin_lock(&fl->hlock); - hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) { - if (buf->size >= size && (!fr || fr->size > buf->size)) - fr = buf; - } - if (fr) - hlist_del_init(&fr->hn); - spin_unlock(&fl->hlock); - if (fr) { - *obuf = fr; - return 0; + if (!remote) { + /* find the smallest buffer that fits in the cache */ + spin_lock(&fl->hlock); + hlist_for_each_entry_safe(buf, n, &fl->cached_bufs, hn) { + if (buf->size >= size && (!fr || fr->size > buf->size)) + fr = buf; + } + if (fr) + hlist_del_init(&fr->hn); + spin_unlock(&fl->hlock); + if (fr) { + *obuf = fr; + return 0; + } } buf = NULL; VERIFY(err, NULL != (buf = kzalloc(sizeof(*buf), GFP_KERNEL))); @@ -773,17 +818,29 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, buf->virt = NULL; buf->phys = 0; buf->size = size; - buf->virt = dma_alloc_coherent(fl->sctx->smmu.dev, buf->size, - (void *)&buf->phys, GFP_KERNEL); + memcpy(&buf->attrs, &attr, sizeof(struct dma_attrs)); + buf->flags = rflags; + buf->raddr = 0; + buf->remote = 0; + buf->virt = dma_alloc_attrs(fl->sctx->smmu.dev, buf->size, + (dma_addr_t *)&buf->phys, + GFP_KERNEL, + (struct dma_attrs *)&buf->attrs); if (IS_ERR_OR_NULL(buf->virt)) { /* free cache and retry */ - fastrpc_buf_list_free(fl); - buf->virt = dma_alloc_coherent(fl->sctx->smmu.dev, buf->size, - (void *)&buf->phys, GFP_KERNEL); + fastrpc_cached_buf_list_free(fl); + buf->virt = dma_alloc_attrs(fl->sctx->smmu.dev, buf->size, + (dma_addr_t *)&buf->phys, + GFP_KERNEL, + (struct dma_attrs *)&buf->attrs); VERIFY(err, !IS_ERR_OR_NULL(buf->virt)); } - if (err) + if (err) { + err = -ENOMEM; + pr_err("adsprpc: %s: %s: dma_alloc_attrs failed for size 0x%zx\n", + current->comm, __func__, size); goto bail; + } if (fl->sctx->smmu.cb) buf->phys += ((uint64_t)fl->sctx->smmu.cb << 32); vmid = fl->apps->channel[fl->cid].vmid; @@ -799,6 +856,13 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, goto bail; } + if (remote) { + INIT_HLIST_NODE(&buf->hn_rem); + spin_lock(&fl->hlock); + hlist_add_head(&buf->hn_rem, &fl->remote_bufs); + spin_unlock(&fl->hlock); + buf->remote = remote; + } *obuf = buf; bail: if (err && buf) @@ -806,7 +870,6 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, return err; } - static int context_restore_interrupted(struct fastrpc_file *fl, struct fastrpc_ioctl_invoke_attrs *inv, struct smq_invoke_ctx **po) @@ -815,6 +878,7 @@ static int context_restore_interrupted(struct fastrpc_file *fl, struct smq_invoke_ctx *ctx = NULL, *ictx = NULL; struct hlist_node *n; struct fastrpc_ioctl_invoke *invoke = &inv->inv; + spin_lock(&fl->hlock); hlist_for_each_entry_safe(ictx, n, &fl->clst.interrupted, hn) { if (ictx->pid == current->pid) { @@ -854,6 +918,7 @@ static int context_build_overlap(struct smq_invoke_ctx *ctx) int outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); int nbufs = inbufs + outbufs; struct overlap max; + 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; @@ -1003,12 +1068,13 @@ bail: static void context_save_interrupted(struct smq_invoke_ctx *ctx) { struct fastrpc_ctx_lst *clst = &ctx->fl->clst; + spin_lock(&ctx->fl->hlock); hlist_del_init(&ctx->hn); hlist_add_head(&ctx->hn, &clst->interrupted); spin_unlock(&ctx->fl->hlock); /* free the cache on power collapse */ - fastrpc_buf_list_free(ctx->fl); + fastrpc_cached_buf_list_free(ctx->fl); } static void context_free(struct smq_invoke_ctx *ctx) @@ -1044,11 +1110,11 @@ static void context_notify_user(struct smq_invoke_ctx *ctx, int retval) complete(&ctx->work); } - static void fastrpc_notify_users(struct fastrpc_file *me) { struct smq_invoke_ctx *ictx; struct hlist_node *n; + spin_lock(&me->hlock); hlist_for_each_entry_safe(ictx, n, &me->clst.pending, hn) { complete(&ictx->work); @@ -1064,6 +1130,7 @@ static void fastrpc_notify_drivers(struct fastrpc_apps *me, int cid) { struct fastrpc_file *fl; struct hlist_node *n; + spin_lock(&me->hlock); hlist_for_each_entry_safe(fl, n, &me->drivers, hn) { if (fl->cid == cid) @@ -1072,6 +1139,7 @@ static void fastrpc_notify_drivers(struct fastrpc_apps *me, int cid) spin_unlock(&me->hlock); } + static void context_list_ctor(struct fastrpc_ctx_lst *me) { INIT_HLIST_HEAD(&me->interrupted); @@ -1083,6 +1151,7 @@ static void fastrpc_context_list_dtor(struct fastrpc_file *fl) struct fastrpc_ctx_lst *clst = &fl->clst; struct smq_invoke_ctx *ictx = NULL, *ctxfree; struct hlist_node *n; + do { ctxfree = NULL; spin_lock(&fl->hlock); @@ -1110,10 +1179,12 @@ static void fastrpc_context_list_dtor(struct fastrpc_file *fl) } static int fastrpc_file_free(struct fastrpc_file *fl); + static void fastrpc_file_list_dtor(struct fastrpc_apps *me) { struct fastrpc_file *fl, *free; struct hlist_node *n; + do { free = NULL; spin_lock(&me->hlock); @@ -1187,7 +1258,10 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) /* allocate new buffer */ if (copylen) { - VERIFY(err, !fastrpc_buf_alloc(ctx->fl, copylen, &ctx->buf)); + DEFINE_DMA_ATTRS(ctx_attrs); + + err = fastrpc_buf_alloc(ctx->fl, copylen, ctx_attrs, + 0, 0, &ctx->buf); if (err) goto bail; } @@ -1206,6 +1280,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) args = (uintptr_t)ctx->buf->virt + metalen; for (i = 0; i < bufs; ++i) { size_t len = lpra[i].buf.len; + list[i].num = 0; list[i].pgidx = 0; if (!len) @@ -1220,6 +1295,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) struct fastrpc_mmap *map = ctx->maps[i]; uint64_t buf = ptr_to_uint64(lpra[i].buf.pv); size_t len = lpra[i].buf.len; + rpra[i].buf.pv = 0; rpra[i].buf.len = len; if (!len) @@ -1561,6 +1637,7 @@ static void smd_event_handler(void *priv, unsigned event) static void fastrpc_init(struct fastrpc_apps *me) { int i; + INIT_HLIST_HEAD(&me->drivers); INIT_HLIST_HEAD(&me->maps); spin_lock_init(&me->hlock); @@ -1684,6 +1761,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl, struct fastrpc_ioctl_init *init = &uproc->init; struct smq_phy_page pages[1]; struct fastrpc_mmap *file = NULL, *mem = NULL; + struct fastrpc_buf *imem = NULL; char *proc_name = NULL; int srcVM[1] = {VMID_HLOS}; int destVM[1] = {gcinfo[0].heap_vmid}; @@ -1696,6 +1774,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl, if (init->flags == FASTRPC_INIT_ATTACH) { remote_arg_t ra[1]; int tgid = current->tgid; + ra[0].buf.pv = (void *)&tgid; ra[0].buf.len = sizeof(tgid); ioctl.inv.handle = 1; @@ -1712,6 +1791,8 @@ static int fastrpc_init_process(struct fastrpc_file *fl, remote_arg_t ra[6]; int fds[6]; int mflags = 0; + int memlen; + DEFINE_DMA_ATTRS(imem_dma_attr); struct { int pgid; unsigned int namelen; @@ -1734,14 +1815,27 @@ static int fastrpc_init_process(struct fastrpc_file *fl, if (err) goto bail; } - if (!access_ok(1, (void const __user *)init->mem, - init->memlen)) - goto bail; inbuf.pageslen = 1; - VERIFY(err, !fastrpc_mmap_create(fl, init->memfd, 0, - init->mem, init->memlen, mflags, &mem)); + + VERIFY(err, !init->mem); + if (err) { + err = -EINVAL; + pr_err("adsprpc: %s: %s: ERROR: donated memory allocated in userspace\n", + current->comm, __func__); + goto bail; + } + memlen = ALIGN(max(1024*1024*3, (int)init->filelen * 4), + 1024*1024); + + dma_set_attr(DMA_ATTR_EXEC_MAPPING, &imem_dma_attr); + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &imem_dma_attr); + dma_set_attr(DMA_ATTR_FORCE_NON_COHERENT, &imem_dma_attr); + + err = fastrpc_buf_alloc(fl, memlen, imem_dma_attr, 0, 0, &imem); if (err) goto bail; + fl->init_mem = imem; + inbuf.pageslen = 1; ra[0].buf.pv = (void *)&inbuf; ra[0].buf.len = sizeof(inbuf); @@ -1755,8 +1849,8 @@ static int fastrpc_init_process(struct fastrpc_file *fl, ra[2].buf.len = inbuf.filelen; fds[2] = init->filefd; - pages[0].addr = mem->phys; - pages[0].size = mem->size; + pages[0].addr = imem->phys; + pages[0].size = imem->size; ra[3].buf.pv = (void *)pages; ra[3].buf.len = 1 * sizeof(*pages); fds[3] = 0; @@ -1896,7 +1990,8 @@ bail: } static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, - struct fastrpc_mmap *map) + uintptr_t va, uint64_t phys, + size_t size, uintptr_t *raddr) { struct fastrpc_ioctl_invoke_attrs ioctl; struct smq_phy_page page; @@ -1913,14 +2008,15 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, struct { uintptr_t vaddrout; } routargs; + inargs.pid = current->tgid; - inargs.vaddrin = (uintptr_t)map->va; + inargs.vaddrin = (uintptr_t)va; inargs.flags = flags; inargs.num = fl->apps->compat ? num * sizeof(page) : num; ra[0].buf.pv = (void *)&inargs; ra[0].buf.len = sizeof(inargs); - page.addr = map->phys; - page.size = map->size; + page.addr = phys; + page.size = size; ra[1].buf.pv = (void *)&page; ra[1].buf.len = num * sizeof(page); @@ -1937,15 +2033,15 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, ioctl.attrs = NULL; VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); - map->raddr = (uintptr_t)routargs.vaddrout; + *raddr = (uintptr_t)routargs.vaddrout; if (err) goto bail; if (flags == ADSP_MMAP_HEAP_ADDR) { struct scm_desc desc = {0}; desc.args[0] = TZ_PIL_AUTH_QDSP6_PROC; - desc.args[1] = map->phys; - desc.args[2] = map->size; + desc.args[1] = phys; + desc.args[2] = size; desc.arginfo = SCM_ARGS(3); err = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, TZ_PIL_PROTECT_MEM_SUBSYS_ID), &desc); @@ -1955,7 +2051,7 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, int destVM[1] = {gcinfo[0].heap_vmid}; int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; - VERIFY(err, !hyp_assign_phys(map->phys, (uint64_t)map->size, + VERIFY(err, !hyp_assign_phys(phys, (uint64_t)size, srcVM, 1, destVM, destVMperm, 1)); if (err) goto bail; @@ -1964,16 +2060,17 @@ bail: return err; } -static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, - struct fastrpc_mmap *map) +static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint64_t phys, + size_t size, uint32_t flags) { int err = 0; int srcVM[1] = {gcinfo[0].heap_vmid}; int destVM[1] = {VMID_HLOS}; int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; - if (map->flags == ADSP_MMAP_HEAP_ADDR) { + if (flags == ADSP_MMAP_HEAP_ADDR) { struct fastrpc_ioctl_invoke_attrs ioctl; + struct scm_desc desc = {0}; remote_arg_t ra[1]; int err = 0; @@ -1997,14 +2094,14 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, if (err) goto bail; desc.args[0] = TZ_PIL_AUTH_QDSP6_PROC; - desc.args[1] = map->phys; - desc.args[2] = map->size; + desc.args[1] = phys; + desc.args[2] = size; desc.args[3] = routargs.skey; desc.arginfo = SCM_ARGS(4); err = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID), &desc); - } else if (map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { - VERIFY(err, !hyp_assign_phys(map->phys, (uint64_t)map->size, + } else if (flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + VERIFY(err, !hyp_assign_phys(phys, (uint64_t)size, srcVM, 1, destVM, destVMperm, 1)); if (err) goto bail; @@ -2014,8 +2111,8 @@ bail: return err; } -static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, - struct fastrpc_mmap *map) +static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, uintptr_t raddr, + uint64_t phys, size_t size, uint32_t flags) { struct fastrpc_ioctl_invoke_attrs ioctl; remote_arg_t ra[1]; @@ -2027,8 +2124,8 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, } inargs; inargs.pid = current->tgid; - inargs.size = map->size; - inargs.vaddrout = map->raddr; + inargs.size = size; + inargs.vaddrout = raddr; ra[0].buf.pv = (void *)&inargs; ra[0].buf.len = sizeof(inargs); @@ -2044,9 +2141,9 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); if (err) goto bail; - if (map->flags == ADSP_MMAP_HEAP_ADDR || - map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { - VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, map)); + if (flags == ADSP_MMAP_HEAP_ADDR || + flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, phys, size, flags)); if (err) goto bail; } @@ -2073,7 +2170,8 @@ static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl) spin_unlock(&me->hlock); if (match) { - VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, match)); + VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, match->phys, + match->size, match->flags)); if (err) goto bail; if (me->channel[0].ramdumpenabled) { @@ -2110,12 +2208,37 @@ static int fastrpc_internal_munmap(struct fastrpc_file *fl, { int err = 0; struct fastrpc_mmap *map = NULL; + struct fastrpc_buf *rbuf = NULL, *free = NULL; + struct hlist_node *n; mutex_lock(&fl->map_mutex); + spin_lock(&fl->hlock); + hlist_for_each_entry_safe(rbuf, n, &fl->remote_bufs, hn_rem) { + if (rbuf->raddr && (rbuf->flags == ADSP_MMAP_ADD_PAGES)) { + if ((rbuf->raddr == ud->vaddrout) && + (rbuf->size == ud->size)) { + free = rbuf; + break; + } + } + } + spin_unlock(&fl->hlock); + + if (free) { + VERIFY(err, !fastrpc_munmap_on_dsp(fl, free->raddr, + free->phys, free->size, free->flags)); + if (err) + goto bail; + fastrpc_buf_free(rbuf, 0); + mutex_unlock(&fl->map_mutex); + return err; + } + VERIFY(err, !fastrpc_mmap_remove(fl, ud->vaddrout, ud->size, &map)); if (err) goto bail; - VERIFY(err, !fastrpc_munmap_on_dsp(fl, map)); + VERIFY(err, !fastrpc_munmap_on_dsp(fl, map->raddr, + map->phys, map->size, map->flags)); if (err) goto bail; fastrpc_mmap_free(map); @@ -2131,22 +2254,55 @@ static int fastrpc_internal_mmap(struct fastrpc_file *fl, { struct fastrpc_mmap *map = NULL; + struct fastrpc_buf *rbuf = NULL; + uintptr_t raddr = 0; int err = 0; mutex_lock(&fl->map_mutex); - if (!fastrpc_mmap_find(fl, ud->fd, (uintptr_t)ud->vaddrin, ud->size, - ud->flags, &map)){ - mutex_unlock(&fl->map_mutex); - return 0; + + if (ud->flags == ADSP_MMAP_ADD_PAGES) { + DEFINE_DMA_ATTRS(dma_attr); + + if (ud->vaddrin) { + err = -EINVAL; + pr_err("adsprpc: %s: %s: ERROR: adding user allocated pages is not supported\n", + current->comm, __func__); + goto bail; + } + dma_set_attr(DMA_ATTR_EXEC_MAPPING, &dma_attr); + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &dma_attr); + dma_set_attr(DMA_ATTR_FORCE_NON_COHERENT, &dma_attr); + + err = fastrpc_buf_alloc(fl, ud->size, dma_attr, ud->flags, + 1, &rbuf); + if (err) + goto bail; + err = fastrpc_mmap_on_dsp(fl, ud->flags, 0, + rbuf->phys, rbuf->size, &raddr); + if (err) + goto bail; + rbuf->raddr = raddr; + } else { + uintptr_t va_to_dsp; + + VERIFY(err, !fastrpc_mmap_create(fl, ud->fd, 0, + (uintptr_t)ud->vaddrin, ud->size, + ud->flags, &map)); + if (err) + goto bail; + + if (ud->flags == ADSP_MMAP_HEAP_ADDR || + ud->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) + va_to_dsp = 0; + else + va_to_dsp = (uintptr_t)map->va; + VERIFY(err, 0 == fastrpc_mmap_on_dsp(fl, ud->flags, va_to_dsp, + map->phys, map->size, &raddr)); + if (err) + goto bail; + map->raddr = raddr; } - VERIFY(err, !fastrpc_mmap_create(fl, ud->fd, 0, - (uintptr_t)ud->vaddrin, ud->size, ud->flags, &map)); - if (err) - goto bail; - VERIFY(err, 0 == fastrpc_mmap_on_dsp(fl, ud->flags, map)); - if (err) - goto bail; - ud->vaddrout = map->raddr; + ud->vaddrout = raddr; bail: if (err && map) fastrpc_mmap_free(map); @@ -2321,15 +2477,16 @@ static int fastrpc_file_free(struct fastrpc_file *fl) spin_unlock(&fl->apps->hlock); kfree(fl->debug_buf); - if (!fl->sctx) { + if (!fl->sctx) goto bail; - } spin_lock(&fl->hlock); fl->file_close = 1; spin_unlock(&fl->hlock); + if (!IS_ERR_OR_NULL(fl->init_mem)) + fastrpc_buf_free(fl->init_mem, 0); fastrpc_context_list_dtor(fl); - fastrpc_buf_list_free(fl); + fastrpc_cached_buf_list_free(fl); hlist_for_each_entry_safe(map, n, &fl->maps, hn) { fastrpc_mmap_free(map); } @@ -2341,6 +2498,7 @@ static int fastrpc_file_free(struct fastrpc_file *fl) if (fl->secsctx) fastrpc_session_free(&fl->apps->channel[cid], fl->secsctx); bail: + fastrpc_remote_buf_list_free(fl); mutex_destroy(&fl->map_mutex); kfree(fl); return 0; @@ -2480,7 +2638,6 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, struct fastrpc_apps *me = &gfa; struct fastrpc_file *fl = filp->private_data; struct hlist_node *n; - struct fastrpc_buf *buf = NULL; struct fastrpc_mmap *map = NULL; struct fastrpc_mmap *gmaps = NULL; struct smq_invoke_ctx *ictx = NULL; @@ -2640,22 +2797,6 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, "%-20d|0x%-20lX\n\n", map->secure, map->attr); } - len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "\n======%s %s %s======\n", title, - " LIST OF BUFS ", title); - spin_lock(&fl->hlock); - len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%-19s|%-19s|%-19s\n", - "virt", "phys", "size"); - len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s%s%s%s%s\n", single_line, single_line, - single_line, single_line, single_line); - hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) { - len += scnprintf(fileinfo + len, - DEBUGFS_SIZE - len, - "0x%-17p|0x%-17llX|%-19zu\n", - buf->virt, (uint64_t)buf->phys, buf->size); - } len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "\n%s %s %s\n", title, " LIST OF PENDING SMQCONTEXTS ", title); @@ -2800,12 +2941,15 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) context_list_ctor(&fl->clst); spin_lock_init(&fl->hlock); INIT_HLIST_HEAD(&fl->maps); - INIT_HLIST_HEAD(&fl->bufs); + INIT_HLIST_HEAD(&fl->cached_bufs); + INIT_HLIST_HEAD(&fl->remote_bufs); INIT_HLIST_NODE(&fl->hn); fl->tgid = current->tgid; fl->apps = me; fl->mode = FASTRPC_MODE_SERIAL; fl->cid = -1; + fl->init_mem = NULL; + if (debugfs_file != NULL) fl->debugfs_file = debugfs_file; memset(&fl->perf, 0, sizeof(fl->perf)); @@ -2843,6 +2987,30 @@ bail: return err; } +static int fastrpc_internal_control(struct fastrpc_file *fl, + struct fastrpc_ioctl_control *cp) +{ + int err = 0; + + VERIFY(err, !IS_ERR_OR_NULL(fl) && !IS_ERR_OR_NULL(fl->apps)); + if (err) + goto bail; + VERIFY(err, !IS_ERR_OR_NULL(cp)); + if (err) + goto bail; + + switch (cp->req) { + case FASTRPC_CONTROL_KALLOC: + cp->kalloc.kalloc_support = 1; + break; + default: + err = -ENOTTY; + break; + } +bail: + return err; +} + static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) { @@ -2852,6 +3020,7 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, struct fastrpc_ioctl_munmap munmap; struct fastrpc_ioctl_init_attrs init; struct fastrpc_ioctl_perf perf; + struct fastrpc_ioctl_control cp; } p; void *param = (char *)ioctl_param; struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data; @@ -2967,8 +3136,22 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, if (err) goto bail; break; + case FASTRPC_IOCTL_CONTROL: + K_COPY_FROM_USER(err, 0, &p.cp, param, + sizeof(p.cp)); + if (err) + goto bail; + VERIFY(err, 0 == (err = fastrpc_internal_control(fl, &p.cp))); + if (err) + goto bail; + if (p.cp.req == FASTRPC_CONTROL_KALLOC) { + K_COPY_TO_USER(err, 0, param, &p.cp, sizeof(p.cp)); + if (err) + goto bail; + } + break; case FASTRPC_IOCTL_GETINFO: - K_COPY_FROM_USER(err, 0, &info, param, sizeof(info)); + K_COPY_FROM_USER(err, 0, &info, param, sizeof(info)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_get_info(fl, &info))); @@ -3283,6 +3466,7 @@ static void fastrpc_deinit(void) } for (j = 0; j < NUM_SESSIONS; j++) { struct fastrpc_session_ctx *sess = &chan->session[j]; + if (sess->smmu.dev) { arm_iommu_detach_device(sess->smmu.dev); sess->smmu.dev = NULL; diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c index e1e061748f22..65a6892344d5 100644 --- a/drivers/char/adsprpc_compat.c +++ b/drivers/char/adsprpc_compat.c @@ -36,6 +36,8 @@ _IOWR('R', 9, struct compat_fastrpc_ioctl_perf) #define COMPAT_FASTRPC_IOCTL_INIT_ATTRS \ _IOWR('R', 10, struct compat_fastrpc_ioctl_init_attrs) +#define COMPAT_FASTRPC_IOCTL_CONTROL \ + _IOWR('R', 12, struct compat_fastrpc_ioctl_control) #define COMPAT_FASTRPC_IOCTL_MMAP_64 \ _IOWR('R', 14, struct compat_fastrpc_ioctl_mmap_64) #define COMPAT_FASTRPC_IOCTL_MUNMAP_64 \ @@ -117,6 +119,18 @@ struct compat_fastrpc_ioctl_perf { /* kernel performance data */ compat_uptr_t keys; }; +#define FASTRPC_CONTROL_KALLOC (3) +struct compat_fastrpc_ctrl_kalloc { + compat_uint_t kalloc_support; /* Remote memory allocation from kernel */ +}; + +struct compat_fastrpc_ioctl_control { + compat_uint_t req; + union { + struct compat_fastrpc_ctrl_kalloc kalloc; + }; +}; + static int compat_get_fastrpc_ioctl_invoke( struct compat_fastrpc_ioctl_invoke_attrs __user *inv32, struct fastrpc_ioctl_invoke_attrs __user **inva, @@ -322,6 +336,19 @@ static int compat_get_fastrpc_ioctl_perf( return err; } +static int compat_get_fastrpc_ioctl_control( + struct compat_fastrpc_ioctl_control __user *ctrl32, + struct fastrpc_ioctl_control __user *ctrl) +{ + compat_uptr_t p; + int err; + + err = get_user(p, &ctrl32->req); + err |= put_user(p, &ctrl->req); + + return err; +} + static int compat_get_fastrpc_ioctl_init( struct compat_fastrpc_ioctl_init_attrs __user *init32, struct fastrpc_ioctl_init_attrs __user *init, @@ -513,6 +540,34 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, case FASTRPC_IOCTL_SETMODE: return filp->f_op->unlocked_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); + case COMPAT_FASTRPC_IOCTL_CONTROL: + { + struct compat_fastrpc_ioctl_control __user *ctrl32; + struct fastrpc_ioctl_control __user *ctrl; + compat_uptr_t p; + + ctrl32 = compat_ptr(arg); + VERIFY(err, NULL != (ctrl = compat_alloc_user_space( + sizeof(*ctrl)))); + if (err) + return -EFAULT; + VERIFY(err, 0 == compat_get_fastrpc_ioctl_control(ctrl32, + ctrl)); + if (err) + return err; + err = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_CONTROL, + (unsigned long)ctrl); + if (err) + return err; + err = get_user(p, &ctrl32->req); + if (err) + return err; + if (p == FASTRPC_CONTROL_KALLOC) { + err = get_user(p, &ctrl->kalloc.kalloc_support); + err |= put_user(p, &ctrl32->kalloc.kalloc_support); + } + return err; + } case COMPAT_FASTRPC_IOCTL_GETPERF: { struct compat_fastrpc_ioctl_perf __user *perf32; diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h index a88c668440c7..4371bf6a2ae7 100644 --- a/drivers/char/adsprpc_shared.h +++ b/drivers/char/adsprpc_shared.h @@ -29,6 +29,7 @@ #define FASTRPC_IOCTL_GETINFO _IOWR('R', 8, uint32_t) #define FASTRPC_IOCTL_GETPERF _IOWR('R', 9, struct fastrpc_ioctl_perf) #define FASTRPC_IOCTL_INIT_ATTRS _IOWR('R', 10, struct fastrpc_ioctl_init_attrs) +#define FASTRPC_IOCTL_CONTROL _IOWR('R', 12, struct fastrpc_ioctl_control) #define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp" #define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp" @@ -188,7 +189,7 @@ struct fastrpc_ioctl_mmap { struct fastrpc_ioctl_mmap_64 { - int fd; /* ion fd */ + int fd; /* ion fd */ uint32_t flags; /* flags for dsp to map with */ uint64_t vaddrin; /* optional virtual address */ size_t size; /* size */ @@ -201,6 +202,31 @@ struct fastrpc_ioctl_perf { /* kernel performance data */ uintptr_t keys; }; +#define FASTRPC_CONTROL_LATENCY (1) +struct fastrpc_ctrl_latency { + uint32_t enable; /* latency control enable */ + uint32_t level; /* level of control */ +}; + +#define FASTRPC_CONTROL_SMMU (2) +struct fastrpc_ctrl_smmu { + uint32_t sharedcb; +}; + +#define FASTRPC_CONTROL_KALLOC (3) +struct fastrpc_ctrl_kalloc { + uint32_t kalloc_support; /* Remote memory allocation from kernel */ +}; + +struct fastrpc_ioctl_control { + uint32_t req; + union { + struct fastrpc_ctrl_latency lp; + struct fastrpc_ctrl_smmu smmu; + struct fastrpc_ctrl_kalloc kalloc; + }; +}; + struct smq_null_invoke { uint64_t ctx; /* invoke caller context */ uint32_t handle; /* handle to invoke */ @@ -245,6 +271,7 @@ static inline struct smq_phy_page *smq_phy_page_start(uint32_t sc, struct smq_invoke_buf *buf) { uint64_t nTotal = REMOTE_SCALARS_INBUFS(sc)+REMOTE_SCALARS_OUTBUFS(sc); + return (struct smq_phy_page *)(&buf[nTotal]); } From 78dbe61ac53679dc203701c203541e3267b44b42 Mon Sep 17 00:00:00 2001 From: Ashish Jain Date: Tue, 30 Jan 2018 14:09:17 +0530 Subject: [PATCH 62/75] soc: qcom: fix race condition while freeing private data WDSP private data structure is freed in wdsp_glink_release() but some of the member variables like work_queue pointer is accessed even after free. Fix this issue by making sure that glink callback functions are finished execution before freeing up wdsp private data structure. Change-Id: Ia4dd9d667109168874dc9188d70741cb9541b0c6 Signed-off-by: Vidyakumar Athota Signed-off-by: Ashish Jain --- drivers/soc/qcom/wcd-dsp-glink.c | 86 +++++++++++++++++++------------- 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/drivers/soc/qcom/wcd-dsp-glink.c b/drivers/soc/qcom/wcd-dsp-glink.c index ee88a8aaf850..50cef91ad5a4 100644 --- a/drivers/soc/qcom/wcd-dsp-glink.c +++ b/drivers/soc/qcom/wcd-dsp-glink.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, 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 @@ -89,6 +89,9 @@ struct wdsp_glink_ch { /* Wait for ch connect state before sending any command */ wait_queue_head_t ch_connect_wait; + /* Wait for ch local and remote disconnect before channel free */ + wait_queue_head_t ch_free_wait; + /* * Glink channel configuration. This has to be the last * member of the strucuture as it has variable size @@ -338,7 +341,7 @@ static void wdsp_glink_notify_state(void *handle, const void *priv, mutex_lock(&ch->mutex); ch->channel_state = event; if (event == GLINK_CONNECTED) { - dev_dbg(wpriv->dev, "%s: glink channel: %s connected\n", + dev_info(wpriv->dev, "%s: glink channel: %s connected\n", __func__, ch->ch_cfg.name); for (i = 0; i < ch->ch_cfg.no_of_intents; i++) { @@ -360,31 +363,29 @@ static void wdsp_glink_notify_state(void *handle, const void *priv, ch->ch_cfg.name); wake_up(&ch->ch_connect_wait); - mutex_unlock(&ch->mutex); } else if (event == GLINK_LOCAL_DISCONNECTED) { /* * Don't use dev_dbg here as dev may not be valid if channel * closed from driver close. */ - pr_debug("%s: channel: %s disconnected locally\n", + pr_info("%s: channel: %s disconnected locally\n", __func__, ch->ch_cfg.name); mutex_unlock(&ch->mutex); - - if (ch->free_mem) { - kfree(ch); - ch = NULL; - } + ch->free_mem = true; + wake_up(&ch->ch_free_wait); + return; } else if (event == GLINK_REMOTE_DISCONNECTED) { - dev_dbg(wpriv->dev, "%s: remote channel: %s disconnected remotely\n", + pr_info("%s: remote channel: %s disconnected remotely\n", __func__, ch->ch_cfg.name); - mutex_unlock(&ch->mutex); /* * If remote disconnect happens, local side also has * to close the channel as per glink design in a * separate work_queue. */ - queue_work(wpriv->work_queue, &ch->lcl_ch_cls_wrk); + if (wpriv && wpriv->work_queue != NULL) + queue_work(wpriv->work_queue, &ch->lcl_ch_cls_wrk); } + mutex_unlock(&ch->mutex); } /* @@ -399,11 +400,11 @@ static int wdsp_glink_close_ch(struct wdsp_glink_ch *ch) mutex_lock(&wpriv->glink_mutex); if (ch->handle) { ret = glink_close(ch->handle); + ch->handle = NULL; if (IS_ERR_VALUE(ret)) { dev_err(wpriv->dev, "%s: glink_close is failed, ret = %d\n", __func__, ret); } else { - ch->handle = NULL; dev_dbg(wpriv->dev, "%s: ch %s is closed\n", __func__, ch->ch_cfg.name); } @@ -451,6 +452,7 @@ static int wdsp_glink_open_ch(struct wdsp_glink_ch *ch) ch->handle = NULL; ret = -EINVAL; } + ch->free_mem = false; } else { dev_err(wpriv->dev, "%s: ch %s is already opened\n", __func__, ch->ch_cfg.name); @@ -492,7 +494,7 @@ static int wdsp_glink_open_all_ch(struct wdsp_glink_priv *wpriv) err_open: for (j = 0; j < i; j++) - if (wpriv->ch[i]) + if (wpriv->ch[j]) wdsp_glink_close_ch(wpriv->ch[j]); done: @@ -631,6 +633,7 @@ static int wdsp_glink_ch_info_init(struct wdsp_glink_priv *wpriv, goto err_ch_mem; } ch[i]->channel_state = GLINK_LOCAL_DISCONNECTED; + ch[i]->free_mem = true; memcpy(&ch[i]->ch_cfg, payload, ch_cfg_size); payload += ch_cfg_size; @@ -654,6 +657,7 @@ static int wdsp_glink_ch_info_init(struct wdsp_glink_priv *wpriv, INIT_WORK(&ch[i]->lcl_ch_open_wrk, wdsp_glink_lcl_ch_open_wrk); INIT_WORK(&ch[i]->lcl_ch_cls_wrk, wdsp_glink_lcl_ch_cls_wrk); init_waitqueue_head(&ch[i]->ch_connect_wait); + init_waitqueue_head(&ch[i]->ch_free_wait); } INIT_WORK(&wpriv->ch_open_cls_wrk, wdsp_glink_ch_open_cls_wrk); @@ -1060,37 +1064,49 @@ static int wdsp_glink_release(struct inode *inode, struct file *file) goto done; } + dev_info(wpriv->dev, "%s: closing wdsp_glink driver\n", __func__); if (wpriv->glink_state.handle) glink_unregister_link_state_cb(wpriv->glink_state.handle); flush_workqueue(wpriv->work_queue); - destroy_workqueue(wpriv->work_queue); - /* - * Clean up glink channel memory in channel state - * callback only if close channels are called from here. + * Wait for channel local and remote disconnect state notifications + * before freeing channel memory. */ - if (wpriv->ch) { - for (i = 0; i < wpriv->no_of_channels; i++) { - if (wpriv->ch[i]) { - wpriv->ch[i]->free_mem = true; - /* - * Channel handle NULL means channel is already - * closed. Free the channel memory here itself. - */ - if (!wpriv->ch[i]->handle) { - kfree(wpriv->ch[i]); - wpriv->ch[i] = NULL; - } else { - wdsp_glink_close_ch(wpriv->ch[i]); - } + for (i = 0; i < wpriv->no_of_channels; i++) { + if (wpriv->ch && wpriv->ch[i]) { + /* + * Only close glink channel from here if REMOTE has + * not already disconnected it + */ + wdsp_glink_close_ch(wpriv->ch[i]); + + ret = wait_event_timeout(wpriv->ch[i]->ch_free_wait, + (wpriv->ch[i]->free_mem == true), + msecs_to_jiffies(TIMEOUT_MS)); + if (!ret) { + pr_err("%s: glink ch %s failed to notify states properly %d\n", + __func__, wpriv->ch[i]->ch_cfg.name, + wpriv->ch[i]->channel_state); + ret = -EINVAL; + goto done; } } - - kfree(wpriv->ch); - wpriv->ch = NULL; } + flush_workqueue(wpriv->work_queue); + destroy_workqueue(wpriv->work_queue); + wpriv->work_queue = NULL; + + for (i = 0; i < wpriv->no_of_channels; i++) { + if (wpriv->ch && wpriv->ch[i]) { + kfree(wpriv->ch[i]); + wpriv->ch[i] = NULL; + } + } + kfree(wpriv->ch); + wpriv->ch = NULL; + mutex_destroy(&wpriv->glink_mutex); mutex_destroy(&wpriv->rsp_mutex); kfree(wpriv); From ef9aa79b43d176ce2ffc255fe5c2ee2fccedc858 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Tue, 21 Aug 2018 10:33:55 -0700 Subject: [PATCH 63/75] msm: ipa3: send usb-connect from rndis-ipa To resolve the timing issue between usb-driver and android framework, made the change on rndis ipa to send the usb-connect msg when usb-driver connect the IPA pipes. Change-Id: I51de37bc7610cb0a94659c64146f10ed322210b2 Acked-by: Pooja Kumari Signed-off-by: Mohammed Javid Signed-off-by: Skylar Chang --- drivers/net/ethernet/msm/rndis_ipa.c | 48 +++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/msm/rndis_ipa.c b/drivers/net/ethernet/msm/rndis_ipa.c index 683f364ed27b..1e0ca8a31888 100644 --- a/drivers/net/ethernet/msm/rndis_ipa.c +++ b/drivers/net/ethernet/msm/rndis_ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, 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 @@ -449,6 +449,11 @@ struct rndis_pkt_hdr rndis_template_hdr = { .zeroes = {0}, }; +static void rndis_ipa_msg_free_cb(void *buff, u32 len, u32 type) +{ + kfree(buff); +} + /** * rndis_ipa_init() - create network device and initialize internal * data structures @@ -648,6 +653,8 @@ int rndis_ipa_pipe_connect_notify(u32 usb_to_ipa_hdl, int next_state; int result; unsigned long flags; + struct ipa_ecm_msg *rndis_msg; + struct ipa_msg_meta msg_meta; RNDIS_IPA_LOG_ENTRY(); @@ -718,6 +725,26 @@ int rndis_ipa_pipe_connect_notify(u32 usb_to_ipa_hdl, } RNDIS_IPA_DEBUG("netif_carrier_on() was called\n"); + rndis_msg = kzalloc(sizeof(*rndis_msg), GFP_KERNEL); + if (!rndis_msg) { + result = -ENOMEM; + goto fail; + } + + memset(&msg_meta, 0, sizeof(struct ipa_msg_meta)); + msg_meta.msg_type = ECM_CONNECT; + msg_meta.msg_len = sizeof(struct ipa_ecm_msg); + strlcpy(rndis_msg->name, rndis_ipa_ctx->net->name, + IPA_RESOURCE_NAME_MAX); + rndis_msg->ifindex = rndis_ipa_ctx->net->ifindex; + + result = ipa_send_msg(&msg_meta, rndis_msg, rndis_ipa_msg_free_cb); + if (result) { + RNDIS_IPA_ERROR("fail to send ECM_CONNECT for rndis\n"); + kfree(rndis_msg); + goto fail; + } + spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_CONNECT); @@ -1165,6 +1192,8 @@ int rndis_ipa_pipe_disconnect_notify(void *private) int outstanding_dropped_pkts; int retval; unsigned long flags; + struct ipa_ecm_msg *rndis_msg; + struct ipa_msg_meta msg_meta; RNDIS_IPA_LOG_ENTRY(); @@ -1192,6 +1221,23 @@ int rndis_ipa_pipe_disconnect_notify(void *private) netif_carrier_off(rndis_ipa_ctx->net); RNDIS_IPA_DEBUG("carrier_off notification was sent\n"); + rndis_msg = kzalloc(sizeof(*rndis_msg), GFP_KERNEL); + if (!rndis_msg) + return -ENOMEM; + + memset(&msg_meta, 0, sizeof(struct ipa_msg_meta)); + msg_meta.msg_type = ECM_DISCONNECT; + msg_meta.msg_len = sizeof(struct ipa_ecm_msg); + strlcpy(rndis_msg->name, rndis_ipa_ctx->net->name, + IPA_RESOURCE_NAME_MAX); + rndis_msg->ifindex = rndis_ipa_ctx->net->ifindex; + + retval = ipa_send_msg(&msg_meta, rndis_msg, rndis_ipa_msg_free_cb); + if (retval) { + RNDIS_IPA_ERROR("fail to send ECM_DISCONNECT for rndis\n"); + kfree(rndis_msg); + return -EPERM; + } netif_stop_queue(rndis_ipa_ctx->net); RNDIS_IPA_DEBUG("queue stopped\n"); From 092de9c89488bed56b2b64246cd25e1b0b859895 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Thu, 23 Aug 2018 05:00:05 +0530 Subject: [PATCH 64/75] msm: adsprpc: allocate all remote memory in kernel Allocate all memory given to remote subsystem in the kernel instead of mapping memory allocated in userspace. Change-Id: I79c1f40d426e271403afa67514714fe6af26cf4e Acked-by: Thyagarajan Venkatanarayanan Signed-off-by: Tharun Kumar Merugu --- drivers/char/adsprpc.c | 385 ++++++++++++++++++++++++++-------- drivers/char/adsprpc_compat.c | 68 ++++++ drivers/char/adsprpc_shared.h | 29 ++- 3 files changed, 389 insertions(+), 93 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 24513e5d1e1e..014bd8842cd2 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -55,6 +55,8 @@ #define TZ_PIL_AUTH_QDSP6_PROC 1 #define ADSP_MMAP_HEAP_ADDR 4 #define ADSP_MMAP_REMOTE_HEAP_ADDR 8 +#define ADSP_MMAP_ADD_PAGES 0x1000 + #define FASTRPC_ENOSUCH 39 #define VMID_SSC_Q6 38 #define VMID_ADSP_Q6 6 @@ -126,6 +128,7 @@ static inline uint64_t buf_num_pages(uint64_t buf, size_t len) static inline uint64_t buf_page_size(uint32_t size) { uint64_t sz = (size + (PAGE_SIZE - 1)) & PAGE_MASK; + return sz > PAGE_SIZE ? sz : PAGE_SIZE; } @@ -145,10 +148,15 @@ struct fastrpc_file; struct fastrpc_buf { struct hlist_node hn; + struct hlist_node hn_rem; struct fastrpc_file *fl; void *virt; uint64_t phys; size_t size; + struct dma_attrs attrs; + uintptr_t raddr; + uint32_t flags; + int remote; }; struct fastrpc_ctx_lst; @@ -292,9 +300,11 @@ struct fastrpc_file { struct hlist_node hn; spinlock_t hlock; struct hlist_head maps; - struct hlist_head bufs; + struct hlist_head cached_bufs; + struct hlist_head remote_bufs; struct fastrpc_ctx_lst clst; struct fastrpc_session_ctx *sctx; + struct fastrpc_buf *init_mem; struct fastrpc_session_ctx *secsctx; uint32_t mode; uint32_t profile; @@ -363,10 +373,17 @@ static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache) return; if (cache) { spin_lock(&fl->hlock); - hlist_add_head(&buf->hn, &fl->bufs); + hlist_add_head(&buf->hn, &fl->cached_bufs); spin_unlock(&fl->hlock); return; } + if (buf->remote) { + spin_lock(&fl->hlock); + hlist_del_init(&buf->hn_rem); + spin_unlock(&fl->hlock); + buf->remote = 0; + buf->raddr = 0; + } if (!IS_ERR_OR_NULL(buf->virt)) { int destVM[1] = {VMID_HLOS}; int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; @@ -380,21 +397,22 @@ static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache) hyp_assign_phys(buf->phys, buf_page_size(buf->size), srcVM, 2, destVM, destVMperm, 1); } - dma_free_coherent(fl->sctx->smmu.dev, buf->size, buf->virt, - buf->phys); + dma_free_attrs(fl->sctx->smmu.dev, buf->size, buf->virt, + buf->phys, (struct dma_attrs *)&buf->attrs); } kfree(buf); } -static void fastrpc_buf_list_free(struct fastrpc_file *fl) +static void fastrpc_cached_buf_list_free(struct fastrpc_file *fl) { struct fastrpc_buf *buf, *free; + do { struct hlist_node *n; free = NULL; spin_lock(&fl->hlock); - hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) { + hlist_for_each_entry_safe(buf, n, &fl->cached_bufs, hn) { hlist_del_init(&buf->hn); free = buf; break; @@ -405,6 +423,25 @@ static void fastrpc_buf_list_free(struct fastrpc_file *fl) } while (free); } +static void fastrpc_remote_buf_list_free(struct fastrpc_file *fl) +{ + struct fastrpc_buf *buf, *free; + + do { + struct hlist_node *n; + + free = NULL; + spin_lock(&fl->hlock); + hlist_for_each_entry_safe(buf, n, &fl->remote_bufs, hn_rem) { + free = buf; + break; + } + spin_unlock(&fl->hlock); + if (free) + fastrpc_buf_free(free, 0); + } while (free); +} + static void fastrpc_mmap_add(struct fastrpc_mmap *map) { if (map->flags == ADSP_MMAP_HEAP_ADDR || @@ -465,23 +502,21 @@ static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd, uintptr_t va, return -ENOTTY; } -static int dma_alloc_memory(phys_addr_t *region_start, size_t size) +static int dma_alloc_memory(dma_addr_t *region_start, void **vaddr, size_t size, + struct dma_attrs *attrs) { struct fastrpc_apps *me = &gfa; - void *vaddr = NULL; - DEFINE_DMA_ATTRS(attrs); if (me->dev == NULL) { pr_err("device adsprpc-mem is not initialized\n"); return -ENODEV; } - dma_set_attr(DMA_ATTR_SKIP_ZEROING, &attrs); - dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); - vaddr = dma_alloc_attrs(me->dev, size, region_start, GFP_KERNEL, - &attrs); - if (!vaddr) { - pr_err("ADSPRPC: Failed to allocate %x remote heap memory\n", - (unsigned int)size); + + *vaddr = dma_alloc_attrs(me->dev, size, region_start, + GFP_KERNEL, attrs); + if (IS_ERR_OR_NULL(*vaddr)) { + pr_err("adsprpc: %s: %s: dma_alloc_attrs failed for size 0x%zx, returned %pK\n", + current->comm, __func__, size, (*vaddr)); return -ENOMEM; } return 0; @@ -617,7 +652,8 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, unsigned attr, struct fastrpc_channel_ctx *chan = &apps->channel[cid]; struct fastrpc_mmap *map = NULL; struct dma_attrs attrs; - phys_addr_t region_start = 0; + dma_addr_t region_start = 0; + void *region_vaddr = NULL; unsigned long flags; int err = 0, vmid; @@ -635,14 +671,20 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, unsigned attr, map->attr = attr; if (mflags == ADSP_MMAP_HEAP_ADDR || mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + DEFINE_DMA_ATTRS(rh_attrs); + + dma_set_attr(DMA_ATTR_SKIP_ZEROING, &rh_attrs); + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &rh_attrs); + map->apps = me; map->fl = NULL; - VERIFY(err, !dma_alloc_memory(®ion_start, len)); + VERIFY(err, !dma_alloc_memory(®ion_start, + ®ion_vaddr, len, &rh_attrs)); if (err) goto bail; map->phys = (uintptr_t)region_start; map->size = len; - map->va = (uintptr_t)map->phys; + map->va = (uintptr_t)region_vaddr; } else { VERIFY(err, !IS_ERR_OR_NULL(map->handle = ion_import_dma_buf(fl->apps->client, fd))); @@ -741,7 +783,8 @@ bail: } static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, - struct fastrpc_buf **obuf) + struct dma_attrs attr, uint32_t rflags, + int remote, struct fastrpc_buf **obuf) { int err = 0, vmid; struct fastrpc_buf *buf = NULL, *fr = NULL; @@ -751,18 +794,20 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, if (err) goto bail; - /* find the smallest buffer that fits in the cache */ - spin_lock(&fl->hlock); - hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) { - if (buf->size >= size && (!fr || fr->size > buf->size)) - fr = buf; - } - if (fr) - hlist_del_init(&fr->hn); - spin_unlock(&fl->hlock); - if (fr) { - *obuf = fr; - return 0; + if (!remote) { + /* find the smallest buffer that fits in the cache */ + spin_lock(&fl->hlock); + hlist_for_each_entry_safe(buf, n, &fl->cached_bufs, hn) { + if (buf->size >= size && (!fr || fr->size > buf->size)) + fr = buf; + } + if (fr) + hlist_del_init(&fr->hn); + spin_unlock(&fl->hlock); + if (fr) { + *obuf = fr; + return 0; + } } buf = NULL; VERIFY(err, NULL != (buf = kzalloc(sizeof(*buf), GFP_KERNEL))); @@ -773,17 +818,29 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, buf->virt = NULL; buf->phys = 0; buf->size = size; - buf->virt = dma_alloc_coherent(fl->sctx->smmu.dev, buf->size, - (void *)&buf->phys, GFP_KERNEL); + memcpy(&buf->attrs, &attr, sizeof(struct dma_attrs)); + buf->flags = rflags; + buf->raddr = 0; + buf->remote = 0; + buf->virt = dma_alloc_attrs(fl->sctx->smmu.dev, buf->size, + (dma_addr_t *)&buf->phys, + GFP_KERNEL, + (struct dma_attrs *)&buf->attrs); if (IS_ERR_OR_NULL(buf->virt)) { /* free cache and retry */ - fastrpc_buf_list_free(fl); - buf->virt = dma_alloc_coherent(fl->sctx->smmu.dev, buf->size, - (void *)&buf->phys, GFP_KERNEL); + fastrpc_cached_buf_list_free(fl); + buf->virt = dma_alloc_attrs(fl->sctx->smmu.dev, buf->size, + (dma_addr_t *)&buf->phys, + GFP_KERNEL, + (struct dma_attrs *)&buf->attrs); VERIFY(err, !IS_ERR_OR_NULL(buf->virt)); } - if (err) + if (err) { + err = -ENOMEM; + pr_err("adsprpc: %s: %s: dma_alloc_attrs failed for size 0x%zx\n", + current->comm, __func__, size); goto bail; + } if (fl->sctx->smmu.cb) buf->phys += ((uint64_t)fl->sctx->smmu.cb << 32); vmid = fl->apps->channel[fl->cid].vmid; @@ -799,6 +856,13 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, goto bail; } + if (remote) { + INIT_HLIST_NODE(&buf->hn_rem); + spin_lock(&fl->hlock); + hlist_add_head(&buf->hn_rem, &fl->remote_bufs); + spin_unlock(&fl->hlock); + buf->remote = remote; + } *obuf = buf; bail: if (err && buf) @@ -806,7 +870,6 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, return err; } - static int context_restore_interrupted(struct fastrpc_file *fl, struct fastrpc_ioctl_invoke_attrs *inv, struct smq_invoke_ctx **po) @@ -815,6 +878,7 @@ static int context_restore_interrupted(struct fastrpc_file *fl, struct smq_invoke_ctx *ctx = NULL, *ictx = NULL; struct hlist_node *n; struct fastrpc_ioctl_invoke *invoke = &inv->inv; + spin_lock(&fl->hlock); hlist_for_each_entry_safe(ictx, n, &fl->clst.interrupted, hn) { if (ictx->pid == current->pid) { @@ -854,6 +918,7 @@ static int context_build_overlap(struct smq_invoke_ctx *ctx) int outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); int nbufs = inbufs + outbufs; struct overlap max; + 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; @@ -1003,12 +1068,13 @@ bail: static void context_save_interrupted(struct smq_invoke_ctx *ctx) { struct fastrpc_ctx_lst *clst = &ctx->fl->clst; + spin_lock(&ctx->fl->hlock); hlist_del_init(&ctx->hn); hlist_add_head(&ctx->hn, &clst->interrupted); spin_unlock(&ctx->fl->hlock); /* free the cache on power collapse */ - fastrpc_buf_list_free(ctx->fl); + fastrpc_cached_buf_list_free(ctx->fl); } static void context_free(struct smq_invoke_ctx *ctx) @@ -1044,11 +1110,11 @@ static void context_notify_user(struct smq_invoke_ctx *ctx, int retval) complete(&ctx->work); } - static void fastrpc_notify_users(struct fastrpc_file *me) { struct smq_invoke_ctx *ictx; struct hlist_node *n; + spin_lock(&me->hlock); hlist_for_each_entry_safe(ictx, n, &me->clst.pending, hn) { complete(&ictx->work); @@ -1064,6 +1130,7 @@ static void fastrpc_notify_drivers(struct fastrpc_apps *me, int cid) { struct fastrpc_file *fl; struct hlist_node *n; + spin_lock(&me->hlock); hlist_for_each_entry_safe(fl, n, &me->drivers, hn) { if (fl->cid == cid) @@ -1072,6 +1139,7 @@ static void fastrpc_notify_drivers(struct fastrpc_apps *me, int cid) spin_unlock(&me->hlock); } + static void context_list_ctor(struct fastrpc_ctx_lst *me) { INIT_HLIST_HEAD(&me->interrupted); @@ -1083,6 +1151,7 @@ static void fastrpc_context_list_dtor(struct fastrpc_file *fl) struct fastrpc_ctx_lst *clst = &fl->clst; struct smq_invoke_ctx *ictx = NULL, *ctxfree; struct hlist_node *n; + do { ctxfree = NULL; spin_lock(&fl->hlock); @@ -1110,10 +1179,12 @@ static void fastrpc_context_list_dtor(struct fastrpc_file *fl) } static int fastrpc_file_free(struct fastrpc_file *fl); + static void fastrpc_file_list_dtor(struct fastrpc_apps *me) { struct fastrpc_file *fl, *free; struct hlist_node *n; + do { free = NULL; spin_lock(&me->hlock); @@ -1187,7 +1258,10 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) /* allocate new buffer */ if (copylen) { - VERIFY(err, !fastrpc_buf_alloc(ctx->fl, copylen, &ctx->buf)); + DEFINE_DMA_ATTRS(ctx_attrs); + + err = fastrpc_buf_alloc(ctx->fl, copylen, ctx_attrs, + 0, 0, &ctx->buf); if (err) goto bail; } @@ -1206,6 +1280,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) args = (uintptr_t)ctx->buf->virt + metalen; for (i = 0; i < bufs; ++i) { size_t len = lpra[i].buf.len; + list[i].num = 0; list[i].pgidx = 0; if (!len) @@ -1220,6 +1295,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) struct fastrpc_mmap *map = ctx->maps[i]; uint64_t buf = ptr_to_uint64(lpra[i].buf.pv); size_t len = lpra[i].buf.len; + rpra[i].buf.pv = 0; rpra[i].buf.len = len; if (!len) @@ -1561,6 +1637,7 @@ static void smd_event_handler(void *priv, unsigned event) static void fastrpc_init(struct fastrpc_apps *me) { int i; + INIT_HLIST_HEAD(&me->drivers); INIT_HLIST_HEAD(&me->maps); spin_lock_init(&me->hlock); @@ -1684,6 +1761,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl, struct fastrpc_ioctl_init *init = &uproc->init; struct smq_phy_page pages[1]; struct fastrpc_mmap *file = NULL, *mem = NULL; + struct fastrpc_buf *imem = NULL; char *proc_name = NULL; int srcVM[1] = {VMID_HLOS}; int destVM[1] = {gcinfo[0].heap_vmid}; @@ -1696,6 +1774,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl, if (init->flags == FASTRPC_INIT_ATTACH) { remote_arg_t ra[1]; int tgid = current->tgid; + ra[0].buf.pv = (void *)&tgid; ra[0].buf.len = sizeof(tgid); ioctl.inv.handle = 1; @@ -1712,6 +1791,8 @@ static int fastrpc_init_process(struct fastrpc_file *fl, remote_arg_t ra[6]; int fds[6]; int mflags = 0; + int memlen; + DEFINE_DMA_ATTRS(imem_dma_attr); struct { int pgid; unsigned int namelen; @@ -1734,14 +1815,27 @@ static int fastrpc_init_process(struct fastrpc_file *fl, if (err) goto bail; } - if (!access_ok(1, (void const __user *)init->mem, - init->memlen)) - goto bail; inbuf.pageslen = 1; - VERIFY(err, !fastrpc_mmap_create(fl, init->memfd, 0, - init->mem, init->memlen, mflags, &mem)); + + VERIFY(err, !init->mem); + if (err) { + err = -EINVAL; + pr_err("adsprpc: %s: %s: ERROR: donated memory allocated in userspace\n", + current->comm, __func__); + goto bail; + } + memlen = ALIGN(max(1024*1024*3, (int)init->filelen * 4), + 1024*1024); + + dma_set_attr(DMA_ATTR_EXEC_MAPPING, &imem_dma_attr); + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &imem_dma_attr); + dma_set_attr(DMA_ATTR_FORCE_NON_COHERENT, &imem_dma_attr); + + err = fastrpc_buf_alloc(fl, memlen, imem_dma_attr, 0, 0, &imem); if (err) goto bail; + fl->init_mem = imem; + inbuf.pageslen = 1; ra[0].buf.pv = (void *)&inbuf; ra[0].buf.len = sizeof(inbuf); @@ -1755,8 +1849,8 @@ static int fastrpc_init_process(struct fastrpc_file *fl, ra[2].buf.len = inbuf.filelen; fds[2] = init->filefd; - pages[0].addr = mem->phys; - pages[0].size = mem->size; + pages[0].addr = imem->phys; + pages[0].size = imem->size; ra[3].buf.pv = (void *)pages; ra[3].buf.len = 1 * sizeof(*pages); fds[3] = 0; @@ -1896,7 +1990,8 @@ bail: } static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, - struct fastrpc_mmap *map) + uintptr_t va, uint64_t phys, + size_t size, uintptr_t *raddr) { struct fastrpc_ioctl_invoke_attrs ioctl; struct smq_phy_page page; @@ -1913,14 +2008,15 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, struct { uintptr_t vaddrout; } routargs; + inargs.pid = current->tgid; - inargs.vaddrin = (uintptr_t)map->va; + inargs.vaddrin = (uintptr_t)va; inargs.flags = flags; inargs.num = fl->apps->compat ? num * sizeof(page) : num; ra[0].buf.pv = (void *)&inargs; ra[0].buf.len = sizeof(inargs); - page.addr = map->phys; - page.size = map->size; + page.addr = phys; + page.size = size; ra[1].buf.pv = (void *)&page; ra[1].buf.len = num * sizeof(page); @@ -1937,15 +2033,15 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, ioctl.attrs = NULL; VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); - map->raddr = (uintptr_t)routargs.vaddrout; + *raddr = (uintptr_t)routargs.vaddrout; if (err) goto bail; if (flags == ADSP_MMAP_HEAP_ADDR) { struct scm_desc desc = {0}; desc.args[0] = TZ_PIL_AUTH_QDSP6_PROC; - desc.args[1] = map->phys; - desc.args[2] = map->size; + desc.args[1] = phys; + desc.args[2] = size; desc.arginfo = SCM_ARGS(3); err = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, TZ_PIL_PROTECT_MEM_SUBSYS_ID), &desc); @@ -1955,7 +2051,7 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, int destVM[1] = {gcinfo[0].heap_vmid}; int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; - VERIFY(err, !hyp_assign_phys(map->phys, (uint64_t)map->size, + VERIFY(err, !hyp_assign_phys(phys, (uint64_t)size, srcVM, 1, destVM, destVMperm, 1)); if (err) goto bail; @@ -1964,16 +2060,17 @@ bail: return err; } -static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, - struct fastrpc_mmap *map) +static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint64_t phys, + size_t size, uint32_t flags) { int err = 0; int srcVM[1] = {gcinfo[0].heap_vmid}; int destVM[1] = {VMID_HLOS}; int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; - if (map->flags == ADSP_MMAP_HEAP_ADDR) { + if (flags == ADSP_MMAP_HEAP_ADDR) { struct fastrpc_ioctl_invoke_attrs ioctl; + struct scm_desc desc = {0}; remote_arg_t ra[1]; int err = 0; @@ -1997,14 +2094,14 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, if (err) goto bail; desc.args[0] = TZ_PIL_AUTH_QDSP6_PROC; - desc.args[1] = map->phys; - desc.args[2] = map->size; + desc.args[1] = phys; + desc.args[2] = size; desc.args[3] = routargs.skey; desc.arginfo = SCM_ARGS(4); err = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID), &desc); - } else if (map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { - VERIFY(err, !hyp_assign_phys(map->phys, (uint64_t)map->size, + } else if (flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + VERIFY(err, !hyp_assign_phys(phys, (uint64_t)size, srcVM, 1, destVM, destVMperm, 1)); if (err) goto bail; @@ -2014,8 +2111,8 @@ bail: return err; } -static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, - struct fastrpc_mmap *map) +static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, uintptr_t raddr, + uint64_t phys, size_t size, uint32_t flags) { struct fastrpc_ioctl_invoke_attrs ioctl; remote_arg_t ra[1]; @@ -2027,8 +2124,8 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, } inargs; inargs.pid = current->tgid; - inargs.size = map->size; - inargs.vaddrout = map->raddr; + inargs.size = size; + inargs.vaddrout = raddr; ra[0].buf.pv = (void *)&inargs; ra[0].buf.len = sizeof(inargs); @@ -2044,9 +2141,9 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); if (err) goto bail; - if (map->flags == ADSP_MMAP_HEAP_ADDR || - map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { - VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, map)); + if (flags == ADSP_MMAP_HEAP_ADDR || + flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, phys, size, flags)); if (err) goto bail; } @@ -2073,7 +2170,8 @@ static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl) spin_unlock(&me->hlock); if (match) { - VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, match)); + VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, match->phys, + match->size, match->flags)); if (err) goto bail; if (me->channel[0].ramdumpenabled) { @@ -2110,12 +2208,37 @@ static int fastrpc_internal_munmap(struct fastrpc_file *fl, { int err = 0; struct fastrpc_mmap *map = NULL; + struct fastrpc_buf *rbuf = NULL, *free = NULL; + struct hlist_node *n; mutex_lock(&fl->map_mutex); + spin_lock(&fl->hlock); + hlist_for_each_entry_safe(rbuf, n, &fl->remote_bufs, hn_rem) { + if (rbuf->raddr && (rbuf->flags == ADSP_MMAP_ADD_PAGES)) { + if ((rbuf->raddr == ud->vaddrout) && + (rbuf->size == ud->size)) { + free = rbuf; + break; + } + } + } + spin_unlock(&fl->hlock); + + if (free) { + VERIFY(err, !fastrpc_munmap_on_dsp(fl, free->raddr, + free->phys, free->size, free->flags)); + if (err) + goto bail; + fastrpc_buf_free(rbuf, 0); + mutex_unlock(&fl->map_mutex); + return err; + } + VERIFY(err, !fastrpc_mmap_remove(fl, ud->vaddrout, ud->size, &map)); if (err) goto bail; - VERIFY(err, !fastrpc_munmap_on_dsp(fl, map)); + VERIFY(err, !fastrpc_munmap_on_dsp(fl, map->raddr, + map->phys, map->size, map->flags)); if (err) goto bail; fastrpc_mmap_free(map); @@ -2131,22 +2254,55 @@ static int fastrpc_internal_mmap(struct fastrpc_file *fl, { struct fastrpc_mmap *map = NULL; + struct fastrpc_buf *rbuf = NULL; + uintptr_t raddr = 0; int err = 0; mutex_lock(&fl->map_mutex); - if (!fastrpc_mmap_find(fl, ud->fd, (uintptr_t)ud->vaddrin, ud->size, - ud->flags, &map)){ - mutex_unlock(&fl->map_mutex); - return 0; + + if (ud->flags == ADSP_MMAP_ADD_PAGES) { + DEFINE_DMA_ATTRS(dma_attr); + + if (ud->vaddrin) { + err = -EINVAL; + pr_err("adsprpc: %s: %s: ERROR: adding user allocated pages is not supported\n", + current->comm, __func__); + goto bail; + } + dma_set_attr(DMA_ATTR_EXEC_MAPPING, &dma_attr); + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &dma_attr); + dma_set_attr(DMA_ATTR_FORCE_NON_COHERENT, &dma_attr); + + err = fastrpc_buf_alloc(fl, ud->size, dma_attr, ud->flags, + 1, &rbuf); + if (err) + goto bail; + err = fastrpc_mmap_on_dsp(fl, ud->flags, 0, + rbuf->phys, rbuf->size, &raddr); + if (err) + goto bail; + rbuf->raddr = raddr; + } else { + uintptr_t va_to_dsp; + + VERIFY(err, !fastrpc_mmap_create(fl, ud->fd, 0, + (uintptr_t)ud->vaddrin, ud->size, + ud->flags, &map)); + if (err) + goto bail; + + if (ud->flags == ADSP_MMAP_HEAP_ADDR || + ud->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) + va_to_dsp = 0; + else + va_to_dsp = (uintptr_t)map->va; + VERIFY(err, 0 == fastrpc_mmap_on_dsp(fl, ud->flags, va_to_dsp, + map->phys, map->size, &raddr)); + if (err) + goto bail; + map->raddr = raddr; } - VERIFY(err, !fastrpc_mmap_create(fl, ud->fd, 0, - (uintptr_t)ud->vaddrin, ud->size, ud->flags, &map)); - if (err) - goto bail; - VERIFY(err, 0 == fastrpc_mmap_on_dsp(fl, ud->flags, map)); - if (err) - goto bail; - ud->vaddrout = map->raddr; + ud->vaddrout = raddr; bail: if (err && map) fastrpc_mmap_free(map); @@ -2321,15 +2477,16 @@ static int fastrpc_file_free(struct fastrpc_file *fl) spin_unlock(&fl->apps->hlock); kfree(fl->debug_buf); - if (!fl->sctx) { + if (!fl->sctx) goto bail; - } spin_lock(&fl->hlock); fl->file_close = 1; spin_unlock(&fl->hlock); + if (!IS_ERR_OR_NULL(fl->init_mem)) + fastrpc_buf_free(fl->init_mem, 0); fastrpc_context_list_dtor(fl); - fastrpc_buf_list_free(fl); + fastrpc_cached_buf_list_free(fl); hlist_for_each_entry_safe(map, n, &fl->maps, hn) { fastrpc_mmap_free(map); } @@ -2341,6 +2498,7 @@ static int fastrpc_file_free(struct fastrpc_file *fl) if (fl->secsctx) fastrpc_session_free(&fl->apps->channel[cid], fl->secsctx); bail: + fastrpc_remote_buf_list_free(fl); mutex_destroy(&fl->map_mutex); kfree(fl); return 0; @@ -2642,7 +2800,7 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, } len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "\n======%s %s %s======\n", title, - " LIST OF BUFS ", title); + " LIST OF CACHED BUFS ", title); spin_lock(&fl->hlock); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%-19s|%-19s|%-19s\n", @@ -2650,7 +2808,7 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%s%s%s%s%s\n", single_line, single_line, single_line, single_line, single_line); - hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) { + hlist_for_each_entry_safe(buf, n, &fl->cached_bufs, hn) { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "0x%-17p|0x%-17llX|%-19zu\n", @@ -2800,12 +2958,15 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) context_list_ctor(&fl->clst); spin_lock_init(&fl->hlock); INIT_HLIST_HEAD(&fl->maps); - INIT_HLIST_HEAD(&fl->bufs); + INIT_HLIST_HEAD(&fl->cached_bufs); + INIT_HLIST_HEAD(&fl->remote_bufs); INIT_HLIST_NODE(&fl->hn); fl->tgid = current->tgid; fl->apps = me; fl->mode = FASTRPC_MODE_SERIAL; fl->cid = -1; + fl->init_mem = NULL; + if (debugfs_file != NULL) fl->debugfs_file = debugfs_file; memset(&fl->perf, 0, sizeof(fl->perf)); @@ -2843,6 +3004,30 @@ bail: return err; } +static int fastrpc_internal_control(struct fastrpc_file *fl, + struct fastrpc_ioctl_control *cp) +{ + int err = 0; + + VERIFY(err, !IS_ERR_OR_NULL(fl) && !IS_ERR_OR_NULL(fl->apps)); + if (err) + goto bail; + VERIFY(err, !IS_ERR_OR_NULL(cp)); + if (err) + goto bail; + + switch (cp->req) { + case FASTRPC_CONTROL_KALLOC: + cp->kalloc.kalloc_support = 1; + break; + default: + err = -ENOTTY; + break; + } +bail: + return err; +} + static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) { @@ -2852,6 +3037,7 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, struct fastrpc_ioctl_munmap munmap; struct fastrpc_ioctl_init_attrs init; struct fastrpc_ioctl_perf perf; + struct fastrpc_ioctl_control cp; } p; void *param = (char *)ioctl_param; struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data; @@ -2967,8 +3153,22 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, if (err) goto bail; break; + case FASTRPC_IOCTL_CONTROL: + K_COPY_FROM_USER(err, 0, &p.cp, param, + sizeof(p.cp)); + if (err) + goto bail; + VERIFY(err, 0 == (err = fastrpc_internal_control(fl, &p.cp))); + if (err) + goto bail; + if (p.cp.req == FASTRPC_CONTROL_KALLOC) { + K_COPY_TO_USER(err, 0, param, &p.cp, sizeof(p.cp)); + if (err) + goto bail; + } + break; case FASTRPC_IOCTL_GETINFO: - K_COPY_FROM_USER(err, 0, &info, param, sizeof(info)); + K_COPY_FROM_USER(err, 0, &info, param, sizeof(info)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_get_info(fl, &info))); @@ -3283,6 +3483,7 @@ static void fastrpc_deinit(void) } for (j = 0; j < NUM_SESSIONS; j++) { struct fastrpc_session_ctx *sess = &chan->session[j]; + if (sess->smmu.dev) { arm_iommu_detach_device(sess->smmu.dev); sess->smmu.dev = NULL; diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c index e1e061748f22..487b60878088 100644 --- a/drivers/char/adsprpc_compat.c +++ b/drivers/char/adsprpc_compat.c @@ -36,6 +36,8 @@ _IOWR('R', 9, struct compat_fastrpc_ioctl_perf) #define COMPAT_FASTRPC_IOCTL_INIT_ATTRS \ _IOWR('R', 10, struct compat_fastrpc_ioctl_init_attrs) +#define COMPAT_FASTRPC_IOCTL_CONTROL \ + _IOWR('R', 12, struct compat_fastrpc_ioctl_control) #define COMPAT_FASTRPC_IOCTL_MMAP_64 \ _IOWR('R', 14, struct compat_fastrpc_ioctl_mmap_64) #define COMPAT_FASTRPC_IOCTL_MUNMAP_64 \ @@ -117,6 +119,31 @@ struct compat_fastrpc_ioctl_perf { /* kernel performance data */ compat_uptr_t keys; }; +#define FASTRPC_CONTROL_LATENCY (1) +struct compat_fastrpc_ctrl_latency { + compat_uint_t enable; /* latency control enable */ + compat_uint_t level; /* level of control */ +}; + +#define FASTRPC_CONTROL_SMMU (2) +struct compat_fastrpc_ctrl_smmu { + compat_uint_t sharedcb; +}; + +#define FASTRPC_CONTROL_KALLOC (3) +struct compat_fastrpc_ctrl_kalloc { + compat_uint_t kalloc_support; /* Remote memory allocation from kernel */ +}; + +struct compat_fastrpc_ioctl_control { + compat_uint_t req; + union { + struct compat_fastrpc_ctrl_latency lp; + struct compat_fastrpc_ctrl_smmu smmu; + struct compat_fastrpc_ctrl_kalloc kalloc; + }; +}; + static int compat_get_fastrpc_ioctl_invoke( struct compat_fastrpc_ioctl_invoke_attrs __user *inv32, struct fastrpc_ioctl_invoke_attrs __user **inva, @@ -322,6 +349,19 @@ static int compat_get_fastrpc_ioctl_perf( return err; } +static int compat_get_fastrpc_ioctl_control( + struct compat_fastrpc_ioctl_control __user *ctrl32, + struct fastrpc_ioctl_control __user *ctrl) +{ + compat_uptr_t p; + int err; + + err = get_user(p, &ctrl32->req); + err |= put_user(p, &ctrl->req); + + return err; +} + static int compat_get_fastrpc_ioctl_init( struct compat_fastrpc_ioctl_init_attrs __user *init32, struct fastrpc_ioctl_init_attrs __user *init, @@ -513,6 +553,34 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, case FASTRPC_IOCTL_SETMODE: return filp->f_op->unlocked_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); + case COMPAT_FASTRPC_IOCTL_CONTROL: + { + struct compat_fastrpc_ioctl_control __user *ctrl32; + struct fastrpc_ioctl_control __user *ctrl; + compat_uptr_t p; + + ctrl32 = compat_ptr(arg); + VERIFY(err, NULL != (ctrl = compat_alloc_user_space( + sizeof(*ctrl)))); + if (err) + return -EFAULT; + VERIFY(err, 0 == compat_get_fastrpc_ioctl_control(ctrl32, + ctrl)); + if (err) + return err; + err = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_CONTROL, + (unsigned long)ctrl); + if (err) + return err; + err = get_user(p, &ctrl32->req); + if (err) + return err; + if (p == FASTRPC_CONTROL_KALLOC) { + err = get_user(p, &ctrl->kalloc.kalloc_support); + err |= put_user(p, &ctrl32->kalloc.kalloc_support); + } + return err; + } case COMPAT_FASTRPC_IOCTL_GETPERF: { struct compat_fastrpc_ioctl_perf __user *perf32; diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h index a88c668440c7..4371bf6a2ae7 100644 --- a/drivers/char/adsprpc_shared.h +++ b/drivers/char/adsprpc_shared.h @@ -29,6 +29,7 @@ #define FASTRPC_IOCTL_GETINFO _IOWR('R', 8, uint32_t) #define FASTRPC_IOCTL_GETPERF _IOWR('R', 9, struct fastrpc_ioctl_perf) #define FASTRPC_IOCTL_INIT_ATTRS _IOWR('R', 10, struct fastrpc_ioctl_init_attrs) +#define FASTRPC_IOCTL_CONTROL _IOWR('R', 12, struct fastrpc_ioctl_control) #define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp" #define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp" @@ -188,7 +189,7 @@ struct fastrpc_ioctl_mmap { struct fastrpc_ioctl_mmap_64 { - int fd; /* ion fd */ + int fd; /* ion fd */ uint32_t flags; /* flags for dsp to map with */ uint64_t vaddrin; /* optional virtual address */ size_t size; /* size */ @@ -201,6 +202,31 @@ struct fastrpc_ioctl_perf { /* kernel performance data */ uintptr_t keys; }; +#define FASTRPC_CONTROL_LATENCY (1) +struct fastrpc_ctrl_latency { + uint32_t enable; /* latency control enable */ + uint32_t level; /* level of control */ +}; + +#define FASTRPC_CONTROL_SMMU (2) +struct fastrpc_ctrl_smmu { + uint32_t sharedcb; +}; + +#define FASTRPC_CONTROL_KALLOC (3) +struct fastrpc_ctrl_kalloc { + uint32_t kalloc_support; /* Remote memory allocation from kernel */ +}; + +struct fastrpc_ioctl_control { + uint32_t req; + union { + struct fastrpc_ctrl_latency lp; + struct fastrpc_ctrl_smmu smmu; + struct fastrpc_ctrl_kalloc kalloc; + }; +}; + struct smq_null_invoke { uint64_t ctx; /* invoke caller context */ uint32_t handle; /* handle to invoke */ @@ -245,6 +271,7 @@ static inline struct smq_phy_page *smq_phy_page_start(uint32_t sc, struct smq_invoke_buf *buf) { uint64_t nTotal = REMOTE_SCALARS_INBUFS(sc)+REMOTE_SCALARS_OUTBUFS(sc); + return (struct smq_phy_page *)(&buf[nTotal]); } From 74bc55d2fa4d6d9014c5ca0c6dceb201471aef05 Mon Sep 17 00:00:00 2001 From: Mohammed Nayeem Ur Rahman Date: Wed, 10 Oct 2018 16:34:37 +0530 Subject: [PATCH 65/75] msm: adsprpc: Fix memory out of bounds error Fixes memory out of bound error. Change-Id: I9cc11b5231ba3654588eadf7a7adca68aff35684 Signed-off-by: Mohammed Nayeem Ur Rahman --- drivers/char/adsprpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 014bd8842cd2..7df66932cba6 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -2948,7 +2948,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) if (err) return err; snprintf(strpid, PID_SIZE, "%d", current->pid); - buf_size = strlen(current->comm) + strlen(strpid) + 1; + buf_size = strlen(current->comm) + strlen("_") + strlen(strpid) + 1; fl->debug_buf = kzalloc(buf_size, GFP_KERNEL); snprintf(fl->debug_buf, UL_SIZE, "%.10s%s%d", current->comm, "_", current->pid); From 9548b41a995363cae9bbb550c3f3b39bcc3b277c Mon Sep 17 00:00:00 2001 From: Sunil Khatri Date: Fri, 7 Oct 2016 15:08:05 +0530 Subject: [PATCH 66/75] ARM: dts: msm: Specify the temperature sensor name for msm8996 Specify the name of GPU temperature sensor in the device tree. This name is used to get the sensor's temperature by querying the thermal driver API. CRs-Fixed: 1064728 Change-Id: Ia93d93a442aa848cbd42a5fb8ecad5ef875f9abf Signed-off-by: Harshdeep Dhatt Signed-off-by: Sunil Khatri Signed-off-by: Archana Sriram --- arch/arm/boot/dts/qcom/msm8996-gpu.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/qcom/msm8996-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8996-gpu.dtsi index 27f692bb14af..c93aef383c53 100644 --- a/arch/arm/boot/dts/qcom/msm8996-gpu.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-gpu.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017,2019 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 @@ -81,6 +81,7 @@ qcom,gpu-qdss-stm = <0x081c0000 0x40000>; // base addr, size + qcom,tsens-name = "tsens_tz_sensor14"; /* Trace bus */ coresight-id = <300>; coresight-name = "coresight-gfx"; From e476b565b0c4d50faede8aaeda2879e21b79a68a Mon Sep 17 00:00:00 2001 From: Amar Singhal Date: Thu, 9 Nov 2017 12:41:45 -0800 Subject: [PATCH 67/75] msm: wlan: Add support for UNI-III ETSI sub-band Per the EU STD. ETSI EN 300 440, sub-band 5725-5875 is allowed in EU at reduced power of 25 mW. Add the sub-band to the EU countries that support this sub-band. CRs-Fixed: 2141740 Change-Id: I0a43e99c4357527f607110faecddd9d0fd444fc6 Signed-off-by: Amar Singhal Signed-off-by: Rajeev Kumar Sirasanagandla --- net/wireless/db.txt | 334 ++++++-------------------------------------- 1 file changed, 46 insertions(+), 288 deletions(-) diff --git a/net/wireless/db.txt b/net/wireless/db.txt index 499d98745d44..4670cf24909c 100644 --- a/net/wireless/db.txt +++ b/net/wireless/db.txt @@ -40,6 +40,7 @@ country AL: DFS-ETSI (5150 - 5250 @ 80), (23), AUTO-BW (5250 - 5350 @ 80), (23), DFS, AUTO-BW (5470 - 5710 @ 160), (30), DFS + (5725 - 5875 @ 80), (14) country AM: DFS-ETSI (2402 - 2482 @ 40), (20) @@ -51,6 +52,7 @@ country AN: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS + (5725 - 5875 @ 80), (14) country AR: (2402 - 2482 @ 40), (36) @@ -74,15 +76,7 @@ country AT: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -112,6 +106,7 @@ country BA: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS + (5725 - 5875 @ 80), (14) country BB: DFS-FCC (2402 - 2482 @ 40), (20) @@ -128,15 +123,7 @@ country BE: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -152,15 +139,7 @@ country BG: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -250,15 +229,7 @@ country CH: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -312,15 +283,7 @@ country CY: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -331,15 +294,7 @@ country CZ: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -354,15 +309,7 @@ country DE: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -371,15 +318,7 @@ country DK: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -415,15 +354,7 @@ country EE: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -437,15 +368,7 @@ country ES: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -460,15 +383,7 @@ country FI: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -484,15 +399,7 @@ country FR: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -501,15 +408,7 @@ country GB: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -530,6 +429,7 @@ country GF: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS + (5725 - 5875 @ 80), (14) country GH: DFS-FCC (2402 - 2482 @ 40), (20) @@ -561,15 +461,7 @@ country GR: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -614,15 +506,7 @@ country HR: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -638,15 +522,7 @@ country HU: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -660,15 +536,7 @@ country IE: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -695,15 +563,7 @@ country IS: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -712,15 +572,7 @@ country IT: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -811,15 +663,7 @@ country LI: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -841,15 +685,7 @@ country LT: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -858,15 +694,7 @@ country LU: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -875,15 +703,7 @@ country LV: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -899,18 +719,21 @@ country MC: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS + (5725 - 5875 @ 80), (14) country MD: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS + (5725 - 5875 @ 80), (14) country ME: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS + (5725 - 5875 @ 80), (14) country MF: DFS-ETSI (2402 - 2482 @ 40), (20) @@ -930,6 +753,7 @@ country MK: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS + (5725 - 5875 @ 80), (14) country MN: DFS-FCC (2402 - 2482 @ 40), (20) @@ -957,6 +781,7 @@ country MQ: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS + (5725 - 5875 @ 80), (14) country MR: DFS-ETSI (2402 - 2482 @ 40), (20) @@ -969,15 +794,7 @@ country MT: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -1044,15 +861,7 @@ country NL: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -1061,15 +870,7 @@ country NO: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -1111,6 +912,7 @@ country PF: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS + (5725 - 5875 @ 80), (14) country PG: DFS-FCC (2402 - 2482 @ 40), (20) @@ -1137,15 +939,7 @@ country PL: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -1154,6 +948,7 @@ country PM: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS + (5725 - 5875 @ 80), (14) country PR: DFS-FCC (2402 - 2472 @ 40), (30) @@ -1174,15 +969,7 @@ country PT: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -1217,15 +1004,7 @@ country RO: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -1236,6 +1015,7 @@ country RS: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -1265,15 +1045,7 @@ country SE: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -1291,15 +1063,7 @@ country SI: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -1308,15 +1072,7 @@ country SK: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5725 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -1376,6 +1132,7 @@ country TR: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS + (5725 - 5875 @ 80), (14) country TT: (2402 - 2482 @ 40), (20) @@ -1462,6 +1219,7 @@ country VC: DFS-ETSI (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW (5490 - 5710 @ 160), (30), DFS + (5725 - 5875 @ 80), (14) country VE: DFS-FCC (2402 - 2482 @ 40), (30) From 28aafa4f4728575e41355a85104f96d563cc5ab6 Mon Sep 17 00:00:00 2001 From: Amar Singhal Date: Mon, 15 Jan 2018 17:16:03 -0800 Subject: [PATCH 68/75] msm: wlan: Remove DSRC channels for US DSRC channels are not required when SRD channels are enabled. Therefore remove them. Signed-off-by: Amar Singhal Change-Id: I1b2937c45d43d31c5689c7c4d134fcfb9a265b0e CRs-Fixed: 2174850 --- net/wireless/db.txt | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/net/wireless/db.txt b/net/wireless/db.txt index 4670cf24909c..5d0f8dd4df67 100644 --- a/net/wireless/db.txt +++ b/net/wireless/db.txt @@ -1184,18 +1184,6 @@ country US: DFS-FCC (5250 - 5330 @ 80), (24), DFS, AUTO-BW (5490 - 5730 @ 160), (24), DFS (5735 - 5835 @ 80), (30) - # 5.9ghz band - # reference: https://apps.fcc.gov/edocs_public/attachmatch/FCC-03-324A1.pdf - (5842 - 5863 @ 5), (30) - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5865 - 5885 @ 20), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5895 - 5915 @ 20), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) # 60g band # reference: http://cfr.regstoday.com/47cfr15.aspx#47_CFR_15p255 # channels 1,2,3,4,5,6 EIRP=40dBm(43dBm peak) From 0524c911285b1ac1eac819ce7701f38d9fc18f26 Mon Sep 17 00:00:00 2001 From: gaolez Date: Fri, 8 Jun 2018 19:44:47 +0800 Subject: [PATCH 69/75] msm: wlan: Update regulatory database Update country ETSI13 related country's frequency range and tx power. Change-Id: Iae27b12df3b36621c395ef9e8a3b1b46461848b6 CRs-Fixed: 2246140 Signed-off-by: Gaole Zhang --- net/wireless/db.txt | 198 ++++++++++++++++++++++---------------------- 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/net/wireless/db.txt b/net/wireless/db.txt index 5d0f8dd4df67..ffcceb6385e3 100644 --- a/net/wireless/db.txt +++ b/net/wireless/db.txt @@ -37,10 +37,10 @@ country AI: DFS-ETSI country AL: DFS-ETSI (2402 - 2482 @ 40), (20) - (5150 - 5250 @ 80), (23), AUTO-BW - (5250 - 5350 @ 80), (23), DFS, AUTO-BW - (5470 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5170 - 5250 @ 80), (23), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country AM: DFS-ETSI (2402 - 2482 @ 40), (20) @@ -51,8 +51,8 @@ country AN: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country AR: (2402 - 2482 @ 40), (36) @@ -75,8 +75,8 @@ country AT: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -105,8 +105,8 @@ country BA: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country BB: DFS-FCC (2402 - 2482 @ 40), (20) @@ -122,8 +122,8 @@ country BE: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -138,8 +138,8 @@ country BG: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -228,8 +228,8 @@ country CH: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -282,8 +282,8 @@ country CY: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -293,8 +293,8 @@ country CZ: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -308,8 +308,8 @@ country DE: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -317,8 +317,8 @@ country DK: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -353,8 +353,8 @@ country EE: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -367,8 +367,8 @@ country ES: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -382,8 +382,8 @@ country FI: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -398,8 +398,8 @@ country FR: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -407,8 +407,8 @@ country GB: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -428,8 +428,8 @@ country GF: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country GH: DFS-FCC (2402 - 2482 @ 40), (20) @@ -460,8 +460,8 @@ country GR: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -505,8 +505,8 @@ country HR: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -521,8 +521,8 @@ country HU: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -535,8 +535,8 @@ country IE: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -562,8 +562,8 @@ country IS: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -571,8 +571,8 @@ country IT: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -662,8 +662,8 @@ country LI: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -684,8 +684,8 @@ country LT: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -693,8 +693,8 @@ country LU: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -702,8 +702,8 @@ country LV: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -718,22 +718,22 @@ country MC: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country MD: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country ME: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country MF: DFS-ETSI (2402 - 2482 @ 40), (20) @@ -752,8 +752,8 @@ country MK: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country MN: DFS-FCC (2402 - 2482 @ 40), (20) @@ -780,8 +780,8 @@ country MQ: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country MR: DFS-ETSI (2402 - 2482 @ 40), (20) @@ -793,17 +793,17 @@ country MT: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) -country MU: DFS-FCC +country MU: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (24), AUTO-BW - (5250 - 5330 @ 80), (24), DFS, AUTO-BW - (5490 - 5730 @ 160), (24), DFS - (5735 - 5835 @ 80), (30) + (5170 - 5250 @ 80), (23), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country MV: DFS-ETSI (2402 - 2482 @ 40), (20) @@ -860,8 +860,8 @@ country NL: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -869,8 +869,8 @@ country NO: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -911,8 +911,8 @@ country PF: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country PG: DFS-FCC (2402 - 2482 @ 40), (20) @@ -938,8 +938,8 @@ country PL: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -947,8 +947,8 @@ country PM: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country PR: DFS-FCC (2402 - 2472 @ 40), (30) @@ -968,8 +968,8 @@ country PT: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -1003,8 +1003,8 @@ country RO: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -1014,8 +1014,8 @@ country RS: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -1044,8 +1044,8 @@ country SE: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -1062,8 +1062,8 @@ country SI: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -1071,8 +1071,8 @@ country SK: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57000 - 66000 @ 2160), (40) @@ -1131,8 +1131,8 @@ country TR: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country TT: (2402 - 2482 @ 40), (20) @@ -1206,8 +1206,8 @@ country VC: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - (5725 - 5875 @ 80), (14) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country VE: DFS-FCC (2402 - 2482 @ 40), (30) From 046b4ced728adca8e8e1605f84fac53dec294402 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 22 Oct 2018 09:12:51 +0800 Subject: [PATCH 70/75] f2fs: fix to account IO correctly Below race can cause reversed reference on dirty count, fix it by relocating __submit_bio() and inc_page_count(). Thread A Thread B - f2fs_inplace_write_data - f2fs_submit_page_bio - __submit_bio - f2fs_write_end_io - dec_page_count - inc_page_count Cc: Fixes: d1b3e72d5490 ("f2fs: submit bio of in-place-update pages") Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim Git-Commit: 2cc5dcf7a9e074c5bdfdefea1801aa0a657750d6 Git-Repo: https://android.googlesource.com/kernel/common Change-Id: Ifff46ef82be68fc910ea3dbcc2299a22664587d4 Signed-off-by: Ritesh Harjani --- fs/f2fs/data.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 3cc679a1d53b..28f1a6e6b83e 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -454,10 +454,10 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) } bio_set_op_attrs(bio, fio->op, fio->op_flags); - __submit_bio(fio->sbi, bio, fio->type); - if (!is_read_io(fio->op)) inc_page_count(fio->sbi, WB_DATA_TYPE(fio->page)); + + __submit_bio(fio->sbi, bio, fio->type); return 0; } From bccbbac9f07271965e7bb2aca8bffec45159ebfb Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Fri, 17 Aug 2018 10:52:17 -0700 Subject: [PATCH 71/75] usb: pd: Don't reject sink request based on max current A fixed sink PDO request includes both operating current and max current. Although the max current requested may be greater than the available source advertisement, as per spec only the operating current request needs to be considered. The sink will likely have also set the Capability Mismatch bit as well. Hence, don't reject the request otherwise the sink will keep re-requesting and never enter a contract. Change-Id: Ia15e2e17abe43f2bcbc1fe7011b70ab0e0f5d9eb Signed-off-by: Jack Pham --- drivers/usb/pd/policy_engine.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index a2cb7147a8ee..540498548978 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -1113,8 +1113,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) case PE_SRC_NEGOTIATE_CAPABILITY: if (PD_RDO_OBJ_POS(pd->rdo) != 1 || PD_RDO_FIXED_CURR(pd->rdo) > - PD_SRC_PDO_FIXED_MAX_CURR(*default_src_caps) || - PD_RDO_FIXED_CURR_MINMAX(pd->rdo) > PD_SRC_PDO_FIXED_MAX_CURR(*default_src_caps)) { /* send Reject */ ret = pd_send_msg(pd, MSG_REJECT, NULL, 0, SOP_MSG); From 6a8e47eb57255baef14e9c2b0471bfd1dd0af2d5 Mon Sep 17 00:00:00 2001 From: Srinivasarao P Date: Tue, 8 Jan 2019 13:52:13 +0530 Subject: [PATCH 72/75] iommu/iommu-debug: fix buffer overflows in debugfs read functions The kernel buffer 'ubuf' can overflow while copying data to user space in debugfs read functions. Fix it by limiting the length of data to be copied to userspace. Change-Id: Ibb3d8c4fb637ddc0e63677ec2dff14a4cf8c0c73 Signed-off-by: Srinivasarao P --- drivers/iommu/iommu-debug.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c index 566572ae051e..629b9158a3cb 100644 --- a/drivers/iommu/iommu-debug.c +++ b/drivers/iommu/iommu-debug.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2019, 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 @@ -1359,6 +1359,7 @@ static ssize_t iommu_debug_dma_attach_read(struct file *file, char __user *ubuf, struct iommu_debug_device *ddev = file->private_data; struct device *dev = ddev->dev; char c[2]; + size_t buflen = sizeof(c); if (*offset) return 0; @@ -1369,13 +1370,14 @@ static ssize_t iommu_debug_dma_attach_read(struct file *file, char __user *ubuf, c[0] = dev->archdata.mapping->domain ? '1' : '0'; c[1] = '\n'; - if (copy_to_user(ubuf, &c, 2)) { + buflen = min(count, buflen); + if (copy_to_user(ubuf, &c, buflen)) { pr_err("copy_to_user failed\n"); return -EFAULT; } *offset = 1; /* non-zero means we're done */ - return 2; + return buflen; } static const struct file_operations iommu_debug_dma_attach_fops = { @@ -1401,7 +1403,7 @@ static ssize_t iommu_debug_virt_addr_read(struct file *file, char __user *ubuf, else snprintf(buf, 100, "0x%pK\n", virt_addr); - buflen = strlen(buf); + buflen = min(count, strlen(buf)+1); if (copy_to_user(ubuf, buf, buflen)) { pr_err("Couldn't copy_to_user\n"); retval = -EFAULT; @@ -1432,19 +1434,21 @@ static ssize_t iommu_debug_attach_read(struct file *file, char __user *ubuf, { struct iommu_debug_device *ddev = file->private_data; char c[2]; + size_t buflen = sizeof(c); if (*offset) return 0; c[0] = ddev->domain ? '1' : '0'; c[1] = '\n'; - if (copy_to_user(ubuf, &c, 2)) { + buflen = min(count, buflen); + if (copy_to_user(ubuf, &c, buflen)) { pr_err("copy_to_user failed\n"); return -EFAULT; } *offset = 1; /* non-zero means we're done */ - return 2; + return buflen; } static const struct file_operations iommu_debug_attach_fops = { @@ -1523,7 +1527,7 @@ static ssize_t iommu_debug_pte_read(struct file *file, char __user *ubuf, else snprintf(buf, 100, "pte=%016llx\n", pte); - buflen = strlen(buf); + buflen = min(count, strlen(buf)+1); if (copy_to_user(ubuf, buf, buflen)) { pr_err("Couldn't copy_to_user\n"); retval = -EFAULT; @@ -1592,7 +1596,7 @@ static ssize_t iommu_debug_atos_read(struct file *file, char __user *ubuf, snprintf(buf, 100, "%pa\n", &phys); } - buflen = strlen(buf); + buflen = min(count, strlen(buf)+1); if (copy_to_user(ubuf, buf, buflen)) { pr_err("Couldn't copy_to_user\n"); retval = -EFAULT; @@ -1645,7 +1649,7 @@ static ssize_t iommu_debug_dma_atos_read(struct file *file, char __user *ubuf, else snprintf(buf, 100, "%pa\n", &phys); - buflen = strlen(buf); + buflen = min(count, strlen(buf)+1); if (copy_to_user(ubuf, buf, buflen)) { pr_err("Couldn't copy_to_user\n"); retval = -EFAULT; @@ -1876,7 +1880,7 @@ static ssize_t iommu_debug_dma_map_read(struct file *file, char __user *ubuf, iova = ddev->iova; snprintf(buf, 100, "%pa\n", &iova); - buflen = strlen(buf); + buflen = min(count, strlen(buf)+1); if (copy_to_user(ubuf, buf, buflen)) { pr_err("Couldn't copy_to_user\n"); retval = -EFAULT; From 4a7a770994cd390e888068f135c346b9658c3c32 Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Sirasanagandla Date: Fri, 18 Jan 2019 13:43:25 +0530 Subject: [PATCH 73/75] msm: wlan: Update ETSI1 and ETSI13 countries In db.txt, update ETSI1 and ETSI13 countries with NO-OUTDOOR flag for frequency ranges: (5170 - 5250) and (5250 - 5330). CRs-Fixed: 2379868 Change-Id: I8a9ce955e82b14814ead5f0bf118608ea90cbc53 Signed-off-by: Rajeev Kumar Sirasanagandla --- net/wireless/db.txt | 292 ++++++++++++++++++++++---------------------- 1 file changed, 146 insertions(+), 146 deletions(-) diff --git a/net/wireless/db.txt b/net/wireless/db.txt index ffcceb6385e3..bc7a70a76685 100644 --- a/net/wireless/db.txt +++ b/net/wireless/db.txt @@ -25,20 +25,20 @@ country AE: DFS-ETSI country AF: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country AI: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country AL: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) @@ -49,8 +49,8 @@ country AM: DFS-ETSI country AN: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) @@ -73,8 +73,8 @@ country AS: DFS-FCC country AT: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -92,8 +92,8 @@ country AU: DFS-FCC country AW: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country AZ: DFS-ETSI @@ -103,8 +103,8 @@ country AZ: DFS-ETSI country BA: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) @@ -120,8 +120,8 @@ country BD: country BE: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -136,8 +136,8 @@ country BF: DFS-FCC country BG: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -150,8 +150,8 @@ country BH: country BL: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country BM: DFS-FCC @@ -192,14 +192,14 @@ country BS: DFS-FCC country BT: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country BY: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country BZ: @@ -226,8 +226,8 @@ country CF: DFS-FCC country CH: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -280,8 +280,8 @@ country CX: DFS-FCC country CY: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -291,8 +291,8 @@ country CY: DFS-ETSI # and http://www.ctu.eu/164/download/VOR/VOR-12-05-2007-6-AN.pdf country CZ: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -306,8 +306,8 @@ country CZ: DFS-ETSI country DE: DFS-ETSI # entries 279004 and 280006 (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -315,8 +315,8 @@ country DE: DFS-ETSI country DK: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -351,8 +351,8 @@ country EC: DFS-FCC country EE: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -365,8 +365,8 @@ country EG: DFS-ETSI country ES: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -374,14 +374,14 @@ country ES: DFS-ETSI country ET: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country FI: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -396,8 +396,8 @@ country FM: DFS-FCC country FR: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -405,8 +405,8 @@ country FR: DFS-ETSI country GB: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -426,8 +426,8 @@ country GE: DFS-ETSI country GF: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) @@ -440,26 +440,26 @@ country GH: DFS-FCC country GI: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country GL: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country GP: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country GR: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -467,8 +467,8 @@ country GR: DFS-ETSI country GT: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country GU: DFS-FCC @@ -503,8 +503,8 @@ country HN: country HR: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -519,8 +519,8 @@ country HT: DFS-FCC country HU: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -533,8 +533,8 @@ country ID: country IE: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -554,14 +554,14 @@ country IN: country IQ: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country IS: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -569,8 +569,8 @@ country IS: DFS-ETSI country IT: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -608,8 +608,8 @@ country KE: DFS-ETSI country KH: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country KN: DFS-FCC @@ -660,8 +660,8 @@ country LC: DFS-FCC country LI: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -676,14 +676,14 @@ country LK: DFS-FCC country LS: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country LT: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -691,8 +691,8 @@ country LT: DFS-ETSI country LU: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -700,8 +700,8 @@ country LU: DFS-ETSI country LV: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -716,29 +716,29 @@ country MA: DFS-ETSI country MC: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) country MD: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) country ME: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) country MF: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country MH: DFS-FCC @@ -750,8 +750,8 @@ country MH: DFS-FCC country MK: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) @@ -778,21 +778,21 @@ country MP: DFS-FCC country MQ: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) country MR: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country MT: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -800,8 +800,8 @@ country MT: DFS-ETSI country MU: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) @@ -813,8 +813,8 @@ country MV: DFS-ETSI country MW: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country MX: DFS-FCC @@ -858,8 +858,8 @@ country NI: DFS-FCC country NL: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -867,8 +867,8 @@ country NL: DFS-ETSI country NO: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -890,8 +890,8 @@ country NZ: DFS-FCC country OM: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country PA: @@ -909,8 +909,8 @@ country PE: DFS-FCC country PF: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) @@ -936,8 +936,8 @@ country PK: country PL: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -945,8 +945,8 @@ country PL: DFS-ETSI country PM: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) @@ -966,8 +966,8 @@ country PS: DFS-FCC country PT: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -995,14 +995,14 @@ country QA: country RE: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country RO: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -1012,8 +1012,8 @@ country RO: DFS-ETSI # http://www.ratel.rs/upload/documents/Plan_namene/Plan_namene-sl_glasnik.pdf country RS: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -1042,8 +1042,8 @@ country SA: DFS-ETSI country SE: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -1060,8 +1060,8 @@ country SG: DFS-FCC country SI: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -1069,8 +1069,8 @@ country SI: DFS-ETSI country SK: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 @@ -1084,8 +1084,8 @@ country SN: country SR: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country SV: DFS-FCC @@ -1103,14 +1103,14 @@ country TC: DFS-FCC country TD: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country TG: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 40), (23) - (5250 - 5330 @ 40), (23), DFS + (5170 - 5250 @ 40), (23), NO-OUTDOOR + (5250 - 5330 @ 40), (23), DFS, NO-OUTDOOR (5490 - 5710 @ 40), (30), DFS country TH: DFS-FCC @@ -1129,8 +1129,8 @@ country TN: DFS-ETSI country TR: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) @@ -1204,8 +1204,8 @@ country UZ: DFS-ETSI country VC: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5730 @ 160), (30), DFS (5735 - 5875 @ 80), (14) @@ -1240,14 +1240,14 @@ country VU: DFS-FCC country WF: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country WS: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 40), (23) - (5250 - 5330 @ 40), (23), DFS + (5170 - 5250 @ 40), (23), NO-OUTDOOR + (5250 - 5330 @ 40), (23), DFS, NO-OUTDOOR (5490 - 5710 @ 40), (30), DFS country XA: DFS-JP @@ -1262,8 +1262,8 @@ country YE: country YT: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS country ZA: DFS-FCC @@ -1277,6 +1277,6 @@ country ZA: DFS-FCC country ZW: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (23), AUTO-BW - (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR (5490 - 5710 @ 160), (30), DFS From 0d2dac557e89a8174adf7af6663b75d53f932e8d Mon Sep 17 00:00:00 2001 From: Meera Gande Date: Wed, 10 Oct 2018 17:09:22 +0530 Subject: [PATCH 74/75] msm: camera: isp: Fix invalid type conversion Due to improper type conversion compilation issue will be seen. Made change to access the appropriate type. Change-Id: I2c61364f0385c83aa304788cc705bf4ca48ac2cc Signed-off-by: Meera Gande --- .../platform/msm/camera_v2/ispif/msm_ispif.c | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c index 9c3bd7b41ce9..da2381d24394 100644 --- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, 2019 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 @@ -230,32 +230,34 @@ static long msm_ispif_cmd_ext(struct v4l2_subdev *sd, long rc = 0; struct ispif_device *ispif = (struct ispif_device *)v4l2_get_subdevdata(sd); - struct ispif_cfg_data_ext pcdata; + struct ispif_cfg_data_ext pcdata = {0}; struct msm_ispif_param_data_ext *params = NULL; + + if (is_compat_task()) { #ifdef CONFIG_COMPAT - struct ispif_cfg_data_ext_32 *pcdata32 = - (struct ispif_cfg_data_ext_32 *)arg; + struct ispif_cfg_data_ext_32 *pcdata32 = + (struct ispif_cfg_data_ext_32 *)arg; - if (pcdata32 == NULL) { - pr_err("Invalid params passed from user\n"); - return -EINVAL; - } - pcdata.cfg_type = pcdata32->cfg_type; - pcdata.size = pcdata32->size; - pcdata.data = compat_ptr(pcdata32->data); - -#else - struct ispif_cfg_data_ext *pcdata64 = + if (pcdata32 == NULL) { + pr_err("Invalid params passed from user\n"); + return -EINVAL; + } + pcdata.cfg_type = pcdata32->cfg_type; + pcdata.size = pcdata32->size; + pcdata.data = compat_ptr(pcdata32->data); +#endif + } else { + struct ispif_cfg_data_ext *pcdata64 = (struct ispif_cfg_data_ext *)arg; - if (pcdata64 == NULL) { - pr_err("Invalid params passed from user\n"); - return -EINVAL; + if (pcdata64 == NULL) { + pr_err("Invalid params passed from user\n"); + return -EINVAL; + } + pcdata.cfg_type = pcdata64->cfg_type; + pcdata.size = pcdata64->size; + pcdata.data = pcdata64->data; } - pcdata.cfg_type = pcdata64->cfg_type; - pcdata.size = pcdata64->size; - pcdata.data = pcdata64->data; -#endif if (pcdata.size != sizeof(struct msm_ispif_param_data_ext)) { pr_err("%s: payload size mismatch\n", __func__); return -EINVAL; From 0655daaa919eea46693be464c5a993306858be43 Mon Sep 17 00:00:00 2001 From: E V Ravi Date: Tue, 8 Jan 2019 17:40:44 +0530 Subject: [PATCH 75/75] msm: ais: ispif: Fix invalid type conversion Due to improper type conversion compilation issue will be seen. Made change to access the appropriate type. Change-Id: I54777fe71a2f29297b439ac26f80b9684222d89a Signed-off-by: E V Ravi --- .../media/platform/msm/ais/ispif/msm_ispif.c | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/drivers/media/platform/msm/ais/ispif/msm_ispif.c b/drivers/media/platform/msm/ais/ispif/msm_ispif.c index 5ddf554d6ef3..ed220c82c11c 100644 --- a/drivers/media/platform/msm/ais/ispif/msm_ispif.c +++ b/drivers/media/platform/msm/ais/ispif/msm_ispif.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2019, 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 @@ -215,32 +215,35 @@ static long msm_ispif_cmd_ext(struct v4l2_subdev *sd, long rc = 0; struct ispif_device *ispif = (struct ispif_device *)v4l2_get_subdevdata(sd); - struct ispif_cfg_data_ext pcdata; + struct ispif_cfg_data_ext pcdata = {0}; struct msm_ispif_param_data_ext *params = NULL; + + if (is_compat_task()) { #ifdef CONFIG_COMPAT - struct ispif_cfg_data_ext_32 *pcdata32 = - (struct ispif_cfg_data_ext_32 *)arg; + struct ispif_cfg_data_ext_32 *pcdata32 = + (struct ispif_cfg_data_ext_32 *)arg; - if (pcdata32 == NULL) { - pr_err("Invalid params passed from user\n"); - return -EINVAL; - } - pcdata.cfg_type = pcdata32->cfg_type; - pcdata.size = pcdata32->size; - pcdata.data = compat_ptr(pcdata32->data); + if (pcdata32 == NULL) { + pr_err("Invalid params passed from user\n"); + return -EINVAL; + } + pcdata.cfg_type = pcdata32->cfg_type; + pcdata.size = pcdata32->size; + pcdata.data = compat_ptr(pcdata32->data); -#else - struct ispif_cfg_data_ext *pcdata64 = - (struct ispif_cfg_data_ext *)arg; - - if (pcdata64 == NULL) { - pr_err("Invalid params passed from user\n"); - return -EINVAL; - } - pcdata.cfg_type = pcdata64->cfg_type; - pcdata.size = pcdata64->size; - pcdata.data = pcdata64->data; #endif + } else { + struct ispif_cfg_data_ext *pcdata64 = + (struct ispif_cfg_data_ext *)arg; + + if (pcdata64 == NULL) { + pr_err("Invalid params passed from user\n"); + return -EINVAL; + } + pcdata.cfg_type = pcdata64->cfg_type; + pcdata.size = pcdata64->size; + pcdata.data = pcdata64->data; + } if (pcdata.size != sizeof(struct msm_ispif_param_data_ext)) { pr_err("%s: payload size mismatch\n", __func__); return -EINVAL;