diff options
29 files changed, 1183 insertions, 90 deletions
diff --git a/Documentation/devicetree/bindings/cache/msm_gladiator_erp_v2.txt b/Documentation/devicetree/bindings/cache/msm_gladiator_erp_v2.txt new file mode 100644 index 000000000000..3c1c5c010ba1 --- /dev/null +++ b/Documentation/devicetree/bindings/cache/msm_gladiator_erp_v2.txt @@ -0,0 +1,20 @@ +* MSM Gladiator error reporting driver + +Required properties: +- compatible: Should be "qcom,msm-gladiator-v2" +- reg: I/O address Gladiator H/W block +- reg-names: Should be "gladiator_base" +- interrupts: Should contain the gladiator error interrupt number +- clock-names: Should be "atb_clk" +- clocks: Handles to clocks specified in "clock-names" property. + +Example: + +qcom,msm-gladiator-v2@b1c0000 { + compatible = "qcom,msm-gladiator-v2"; + reg = <0xb1c0000 0xe000>; + reg-names = "gladiator_base"; + interrupts = <0 34 0>; + clock-names = "atb_clk"; + clocks = <&clock_gcc clk_qdss_clk>; +} diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi.txt b/Documentation/devicetree/bindings/fb/mdss-dsi.txt index e978646b54f4..50e12ccde14f 100644 --- a/Documentation/devicetree/bindings/fb/mdss-dsi.txt +++ b/Documentation/devicetree/bindings/fb/mdss-dsi.txt @@ -84,8 +84,6 @@ Required properties: - qcom,mdss-fb-map-prim: pHandle that specifies the framebuffer to which the primary interface is mapped. - qcom,mdss-mdp: pHandle that specifies the mdss-mdp device. -- qcom,platform-regulator-settings: An array of length 7 or 5 that specifies the PHY - regulator settings. It use 5 bytes for 8996 pll. - qcom,platform-strength-ctrl: An array of length 2 or 10 that specifies the PHY strengthCtrl settings. It use 10 bytes for 8996 pll. - qcom,platform-lane-config: An array of length 45 or 20 that specifies the PHY @@ -113,6 +111,8 @@ Optional properties: controller. These pin configurations are installed in the pinctrl device node. Refer to pinctrl-bindings.txt - qcom,regulator-ldo-mode: Boolean to enable ldo mode for the dsi phy regulator +- qcom,platform-regulator-settings: An array of length 7 or 5 that specifies the PHY + regulator settings. It use 5 bytes for 8996 pll. - qcom,null-insertion-enabled: Boolean to enable NULL packet insertion feature for DSI controller. - qcom,dsi-irq-line: Boolean specifies if DSI has a different irq line than mdp. diff --git a/Documentation/devicetree/bindings/media/video/msm-jpegdma.txt b/Documentation/devicetree/bindings/media/video/msm-jpegdma.txt index 035bd6a659d6..6b05e7fa3084 100644 --- a/Documentation/devicetree/bindings/media/video/msm-jpegdma.txt +++ b/Documentation/devicetree/bindings/media/video/msm-jpegdma.txt @@ -19,13 +19,18 @@ Required properties: - clocks : clocks required for the device. - qcom,clock-rates: should specify clock rates in Hz to each clocks property defined. +- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for + below optional properties: + - qcom,msm-bus,name + - qcom,msm-bus,num-cases + - qcom,msm-bus,num-paths + - qcom,msm-bus,vectors-KBps + Optional properties: -- qcom,qos-regs: relative address offsets of QoS registers. -- qcom,qos-settings: QoS values to be written to QoS registers. -- qcom,vbif-regs: relative address offsets of VBIF registers. -- qcom,vbif-settings: VBIF values to be written to VBIF registers. -- qcom,prefetch-regs: relative address offsets of MMU prefetch registers. -- qcom,prefetch-settings: values to be written to MMU Prefetch registers. +- qcom,vbif-reg-settings: relative address offsets and value pairs for VBIF registers. +- qcom,qos-reg-settings: relative address offsets and value pairs for QoS registers. +- qcom,prefetch-reg-settings: relative address offsets and value pairs for + MMU prefetch registers. Example: qcom,jpegdma@aa0000 { @@ -53,10 +58,14 @@ Example: <&clock_gcc clk_mmssnoc_axi_clk>, <&clock_mmss clk_mmagic_camss_axi_clk>; qcom,clock-rates = <266670000 0 0 0 0 0 0 0 0>, - <400000000 0 0 0 0 0 0 0 0>; - qcom,vbif-regs = <0x4 0xDC 0x124 0x160>; - qcom,vbif-settings = <0x1 0x7 0x1 0x22222222>; - qcom,prefetch-regs = <0x18C 0x1A0 0x1B0>; - qcom,prefetch-settings = <0x11 0x31 0x31>; + qcom,vbif-reg-settings = <0x4 0x1>; + qcom,prefetch-reg-settings = <0x18c 0x11>, + <0x1a0 0x31>, + <0x1b0 0x31>; + qcom,msm-bus,name = "msm_camera_jpeg_dma"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = <62 512 0 0>, + <62 512 666675 666675>; status = "ok"; }; diff --git a/arch/arm/boot/dts/qcom/msm-arm-smmu-cobalt.dtsi b/arch/arm/boot/dts/qcom/msm-arm-smmu-cobalt.dtsi index b0963faab701..f00395b081b8 100644 --- a/arch/arm/boot/dts/qcom/msm-arm-smmu-cobalt.dtsi +++ b/arch/arm/boot/dts/qcom/msm-arm-smmu-cobalt.dtsi @@ -11,6 +11,7 @@ */ #include <dt-bindings/clock/msm-clocks-cobalt.h> +#include <dt-bindings/msm/msm-bus-ids.h> #include <dt-bindings/interrupt-controller/arm-gic.h> &soc { @@ -150,12 +151,7 @@ "mmss_bimc_smmu_ahb_clk", "mmss_bimc_smmu_axi_clk"; #clock-cells = <1>; - /* - * The iommu test framework requires at least one iommu - * client to populate debugfs. The presence of a device - * "qcom,smmu-v2" alone is not sufficient. - */ - iommus = <&mmss_smmu 1>; + qcom,bus-master-id = <MSM_BUS_MNOC_BIMC_MAS>; }; kgsl_smmu: arm,smmu-kgsl@5040000 { @@ -177,8 +173,13 @@ <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>; vdd-supply = <&gdsc_gpu_cx>; - clocks = <&clock_gcc clk_gcc_bimc_gfx_clk>; - clock-name = "kgsl_smmu_clk"; + clocks = <&clock_gcc clk_gcc_gpu_cfg_ahb_clk>, + <&clock_gcc clk_gcc_bimc_gfx_clk>, + <&clock_gcc clk_gcc_gpu_bimc_gfx_clk>; + + clock-names = "gcc_gpu_cfg_ahb_clk", + "gcc_bimc_gfx_clk", + "gcc_gpu_bimc_gfx_clk"; #clock-cells = <1>; }; }; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi index d3ce12850911..d2d6d85847a6 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi @@ -84,3 +84,9 @@ status = "ok"; }; + +&uartblsp2dm1 { + status = "ok"; + pinctrl-names = "default"; + pinctrl-0 = <&uart_console_active>; +}; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi index 0c77a1b4e417..885e71ac9c0f 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi @@ -84,3 +84,9 @@ status = "ok"; }; + +&uartblsp2dm1 { + status = "ok"; + pinctrl-names = "default"; + pinctrl-0 = <&uart_console_active>; +}; diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi index 01f0e6a4fd2a..36a7eb9a2469 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi @@ -823,6 +823,15 @@ qcom,config-reg = <0x179d1434>; }; + qcom,msm-gladiator-v2@17900000 { + compatible = "qcom,msm-gladiator-v2"; + reg = <0x17900000 0xe000>; + reg-names = "gladiator_base"; + interrupts = <0 22 0>; + clock-names = "atb_clk"; + clocks = <&clock_gcc clk_qdss_clk>; + }; + qcom,smem@86000000 { compatible = "qcom,smem"; reg = <0x86000000 0x200000>, diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig index 5791959408bd..bf58ebcdcf74 100644 --- a/arch/arm64/configs/msm-perf_defconfig +++ b/arch/arm64/configs/msm-perf_defconfig @@ -208,6 +208,9 @@ CONFIG_NET_EMATCH_U32=y CONFIG_NET_EMATCH_META=y CONFIG_NET_EMATCH_TEXT=y CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_GACT=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_SKBEDIT=y CONFIG_RMNET_DATA=y CONFIG_RMNET_DATA_FC=y CONFIG_RMNET_DATA_DEBUG_PKT=y @@ -256,6 +259,7 @@ CONFIG_DM_REQ_CRYPT=y CONFIG_DM_UEVENT=y CONFIG_DM_VERITY=y CONFIG_NETDEVICES=y +CONFIG_BONDING=y CONFIG_TUN=y CONFIG_VIRTIO_NET=y CONFIG_SKY2=y diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig index deffb3241e12..9e58c254e1a8 100644 --- a/arch/arm64/configs/msm_defconfig +++ b/arch/arm64/configs/msm_defconfig @@ -210,6 +210,9 @@ CONFIG_NET_EMATCH_U32=y CONFIG_NET_EMATCH_META=y CONFIG_NET_EMATCH_TEXT=y CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_GACT=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_SKBEDIT=y CONFIG_RMNET_DATA=y CONFIG_RMNET_DATA_FC=y CONFIG_RMNET_DATA_DEBUG_PKT=y @@ -259,6 +262,7 @@ CONFIG_DM_REQ_CRYPT=y CONFIG_DM_UEVENT=y CONFIG_DM_VERITY=y CONFIG_NETDEVICES=y +CONFIG_BONDING=y CONFIG_TUN=y CONFIG_VIRTIO_NET=y CONFIG_SKY2=y diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig index 0b075acbc8e4..8c5f26f42398 100644 --- a/arch/arm64/configs/msmcortex-perf_defconfig +++ b/arch/arm64/configs/msmcortex-perf_defconfig @@ -382,6 +382,8 @@ CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_EFI=y CONFIG_DMADEVICES=y CONFIG_QCOM_BAM_DMA=y +CONFIG_UIO=y +CONFIG_UIO_MSM_SHAREDMEM=y CONFIG_VIRTIO_PCI=y CONFIG_VIRTIO_BALLOON=y CONFIG_VIRTIO_MMIO=y @@ -439,6 +441,7 @@ CONFIG_MEM_SHARE_QMI_SERVICE=y CONFIG_EXTCON=y CONFIG_PWM=y CONFIG_PWM_QPNP=y +CONFIG_ARM_GIC_V3_ACL=y CONFIG_PHY_XGENE=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig index 9c571aab8fc8..a7860f50757f 100644 --- a/arch/arm64/configs/msmcortex_defconfig +++ b/arch/arm64/configs/msmcortex_defconfig @@ -401,6 +401,8 @@ CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_EFI=y CONFIG_DMADEVICES=y CONFIG_QCOM_BAM_DMA=y +CONFIG_UIO=y +CONFIG_UIO_MSM_SHAREDMEM=y CONFIG_VIRTIO_PCI=y CONFIG_VIRTIO_BALLOON=y CONFIG_VIRTIO_MMIO=y @@ -449,6 +451,8 @@ CONFIG_QCOM_SCM_XPU=y CONFIG_QCOM_WATCHDOG_V2=y CONFIG_QCOM_MEMORY_DUMP_V2=y CONFIG_ICNSS=y +CONFIG_MSM_GLADIATOR_ERP_V2=y +CONFIG_PANIC_ON_GLADIATOR_ERROR_V2=y CONFIG_MSM_GLADIATOR_HANG_DETECT=y CONFIG_MSM_CORE_HANG_DETECT=y CONFIG_MSM_BOOT_STATS=y @@ -464,6 +468,7 @@ CONFIG_MEM_SHARE_QMI_SERVICE=y CONFIG_EXTCON=y CONFIG_PWM=y CONFIG_PWM_QPNP=y +CONFIG_ARM_GIC_V3_ACL=y CONFIG_PHY_XGENE=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index feb6b4efa641..34aa4b3b47e9 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -24,6 +24,8 @@ #define MIDR_CORTEX_A53 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53) #define MIDR_CORTEX_A57 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57) #define MIDR_THUNDERX MIDR_CPU_PART(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) +#define MIDR_KRYO2XX_SILVER \ + MIDR_CPU_PART(ARM_CPU_IMP_QCOM, ARM_CPU_PART_KRYO2XX_SILVER) #define CPU_MODEL_MASK (MIDR_IMPLEMENTOR_MASK | MIDR_PARTNUM_MASK | \ MIDR_ARCHITECTURE_MASK) @@ -91,6 +93,12 @@ const struct arm64_cpu_capabilities arm64_errata[] = { .capability = ARM64_WORKAROUND_845719, MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x04), }, + { + /* Kryo2xx Silver rAp4 */ + .desc = "Kryo2xx Silver erratum 845719", + .capability = ARM64_WORKAROUND_845719, + MIDR_RANGE(MIDR_KRYO2XX_SILVER, 0xA00004, 0xA00004), + }, #endif #ifdef CONFIG_CAVIUM_ERRATUM_23154 { diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h index 53968aaf76f9..c51ee50de738 100644 --- a/arch/um/include/asm/thread_info.h +++ b/arch/um/include/asm/thread_info.h @@ -62,6 +62,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_SYSCALL_AUDIT 6 #define TIF_RESTORE_SIGMASK 7 #define TIF_NOTIFY_RESUME 8 +#define TIF_MM_RELEASED 9 #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) diff --git a/drivers/base/regmap/regmap-spmi.c b/drivers/base/regmap/regmap-spmi.c index 7e58f6560399..156751544c02 100644 --- a/drivers/base/regmap/regmap-spmi.c +++ b/drivers/base/regmap/regmap-spmi.c @@ -1,7 +1,7 @@ /* * Register map access API - SPMI support * - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013,2016 The Linux Foundation. All rights reserved. * * Based on regmap-i2c.c: * Copyright 2011 Wolfson Microelectronics plc @@ -142,7 +142,7 @@ static int regmap_spmi_ext_read(void *context, while (val_size) { len = min_t(size_t, val_size, 8); - err = spmi_ext_register_readl(context, addr, val, val_size); + err = spmi_ext_register_readl(context, addr, val, len); if (err) goto err_out; diff --git a/drivers/clk/msm/clock-mmss-cobalt.c b/drivers/clk/msm/clock-mmss-cobalt.c index ba9196b7abc9..777571bb7c96 100644 --- a/drivers/clk/msm/clock-mmss-cobalt.c +++ b/drivers/clk/msm/clock-mmss-cobalt.c @@ -1746,13 +1746,36 @@ static struct branch_clk mmss_mdss_byte0_clk = { }, }; +static struct div_clk mmss_mdss_byte0_intf_div_clk = { + .offset = MMSS_MDSS_BYTE0_INTF_DIV, + .mask = 0x3, + .shift = 0, + .data = { + .min_div = 1, + .max_div = 4, + }, + .base = &virt_base, + /* + * NOTE: Op does not work for div-3. Current assumption is that div-3 + * is not a recommended setting for this divider. + */ + .ops = &postdiv_reg_ops, + .c = { + .dbg_name = "mmss_mdss_byte0_intf_div_clk", + .parent = &byte0_clk_src.c, + .ops = &clk_ops_slave_div, + .flags = CLKFLAG_NO_RATE_CACHE, + CLK_INIT(mmss_mdss_byte0_intf_div_clk.c), + }, +}; + static struct branch_clk mmss_mdss_byte0_intf_clk = { .cbcr_reg = MMSS_MDSS_BYTE0_INTF_CBCR, - .has_sibling = 1, + .has_sibling = 0, .base = &virt_base, .c = { .dbg_name = "mmss_mdss_byte0_intf_clk", - .parent = &byte0_clk_src.c, + .parent = &mmss_mdss_byte0_intf_div_clk.c, .ops = &clk_ops_branch, CLK_INIT(mmss_mdss_byte0_intf_clk.c), }, @@ -1770,13 +1793,36 @@ static struct branch_clk mmss_mdss_byte1_clk = { }, }; +static struct div_clk mmss_mdss_byte1_intf_div_clk = { + .offset = MMSS_MDSS_BYTE1_INTF_DIV, + .mask = 0x3, + .shift = 0, + .data = { + .min_div = 1, + .max_div = 4, + }, + .base = &virt_base, + /* + * NOTE: Op does not work for div-3. Current assumption is that div-3 + * is not a recommended setting for this divider. + */ + .ops = &postdiv_reg_ops, + .c = { + .dbg_name = "mmss_mdss_byte1_intf_div_clk", + .parent = &byte1_clk_src.c, + .ops = &clk_ops_slave_div, + .flags = CLKFLAG_NO_RATE_CACHE, + CLK_INIT(mmss_mdss_byte1_intf_div_clk.c), + }, +}; + static struct branch_clk mmss_mdss_byte1_intf_clk = { .cbcr_reg = MMSS_MDSS_BYTE1_INTF_CBCR, - .has_sibling = 1, + .has_sibling = 0, .base = &virt_base, .c = { .dbg_name = "mmss_mdss_byte1_intf_clk", - .parent = &byte1_clk_src.c, + .parent = &mmss_mdss_byte1_intf_div_clk.c, .ops = &clk_ops_branch, CLK_INIT(mmss_mdss_byte1_intf_clk.c), }, @@ -2406,8 +2452,10 @@ static struct clk_lookup msm_clocks_mmss_cobalt[] = { CLK_LIST(mmss_mdss_ahb_clk), CLK_LIST(mmss_mdss_axi_clk), CLK_LIST(mmss_mdss_byte0_clk), + CLK_LIST(mmss_mdss_byte0_intf_div_clk), CLK_LIST(mmss_mdss_byte0_intf_clk), CLK_LIST(mmss_mdss_byte1_clk), + CLK_LIST(mmss_mdss_byte0_intf_div_clk), CLK_LIST(mmss_mdss_byte1_intf_clk), CLK_LIST(mmss_mdss_dp_aux_clk), CLK_LIST(mmss_mdss_dp_gtc_clk), diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c index 034789880a1f..2f84ff95a38a 100644 --- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c +++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c @@ -17,6 +17,8 @@ #include <linux/ion.h> #include <linux/msm_ion.h> #include <linux/delay.h> +#include <linux/uaccess.h> +#include <linux/compat.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> #include <media/videobuf2-core.h> @@ -70,18 +72,31 @@ static struct msm_jpegdma_format formats[] = { .planes[1] = JPEGDMA_PLANE_TYPE_CBCR, }, { - .name = "YUV 4:2:0 planar, YCbCr", - .fourcc = V4L2_PIX_FMT_YUV420, + .name = "YVU 4:2:0 planar, YCrCb", + .fourcc = V4L2_PIX_FMT_YVU420, .depth = 12, .num_planes = 3, - .colplane_h = 2, - .colplane_v = 2, + .colplane_h = 1, + .colplane_v = 4, .h_align = 2, .v_align = 2, .planes[0] = JPEGDMA_PLANE_TYPE_Y, .planes[1] = JPEGDMA_PLANE_TYPE_CR, .planes[2] = JPEGDMA_PLANE_TYPE_CB, }, + { + .name = "YUV 4:2:0 planar, YCbCr", + .fourcc = V4L2_PIX_FMT_YUV420, + .depth = 12, + .num_planes = 3, + .colplane_h = 1, + .colplane_v = 4, + .h_align = 2, + .v_align = 2, + .planes[0] = JPEGDMA_PLANE_TYPE_Y, + .planes[1] = JPEGDMA_PLANE_TYPE_CB, + .planes[2] = JPEGDMA_PLANE_TYPE_CR, + }, }; /* @@ -196,7 +211,8 @@ static void msm_jpegdma_align_format(struct v4l2_format *f, int format_idx) if (formats[format_idx].num_planes > 1) for (i = 1; i < formats[format_idx].num_planes; i++) size_image += (f->fmt.pix.bytesperline * - (f->fmt.pix.height / formats[format_idx].colplane_v)); + (f->fmt.pix.height / + formats[format_idx].colplane_v)); f->fmt.pix.sizeimage = size_image; f->fmt.pix.field = V4L2_FIELD_NONE; @@ -250,6 +266,9 @@ static int msm_jpegdma_update_hw_config(struct jpegdma_ctx *ctx) size.fps = ctx->timeperframe.denominator / ctx->timeperframe.numerator; + size.in_offset = ctx->in_offset; + size.out_offset = ctx->out_offset; + size.format = formats[ctx->format_idx]; msm_jpegdma_fill_size_from_ctx(ctx, &size); @@ -364,7 +383,9 @@ static void msm_jpegdma_stop_streaming(struct vb2_queue *q) dev_err(ctx->jdma_device->dev, "Ctx wait timeout\n"); ret = -ETIME; } - msm_jpegdma_hw_put(ctx->jdma_device); + + if (ctx->jdma_device->ref_count > 0) + msm_jpegdma_hw_put(ctx->jdma_device); } /* Videobuf2 queue callbacks. */ @@ -388,13 +409,29 @@ static void *msm_jpegdma_get_userptr(void *alloc_ctx, { struct msm_jpegdma_device *dma = alloc_ctx; struct msm_jpegdma_buf_handle *buf; + struct msm_jpeg_dma_buff __user *up_buff = compat_ptr(vaddr); + struct msm_jpeg_dma_buff kp_buff; int ret; + if (!access_ok(VERIFY_READ, up_buff, + sizeof(struct msm_jpeg_dma_buff)) || + get_user(kp_buff.fd, &up_buff->fd)) { + dev_err(dma->dev, "Error getting user data\n"); + return ERR_PTR(-ENOMEM); + } + + if (!access_ok(VERIFY_WRITE, up_buff, + sizeof(struct msm_jpeg_dma_buff)) || + put_user(kp_buff.fd, &up_buff->fd)) { + dev_err(dma->dev, "Error putting user data\n"); + return ERR_PTR(-ENOMEM); + } + buf = kzalloc(sizeof(*buf), GFP_KERNEL); if (!buf) return ERR_PTR(-ENOMEM); - ret = msm_jpegdma_hw_map_buffer(dma, vaddr, buf); + ret = msm_jpegdma_hw_map_buffer(dma, kp_buff.fd, buf); if (ret < 0 || buf->size < size) goto error; @@ -482,7 +519,6 @@ static int msm_jpegdma_open(struct file *file) if (!ctx) return -ENOMEM; - mutex_init(&ctx->lock); ctx->jdma_device = device; dev_dbg(ctx->jdma_device->dev, "Jpeg v4l2 dma open\n"); /* Set ctx defaults */ @@ -531,7 +567,9 @@ static int msm_jpegdma_release(struct file *file) struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(file->private_data); /* release all the resources */ - msm_jpegdma_hw_put(ctx->jdma_device); + if (ctx->jdma_device->ref_count > 0) + msm_jpegdma_hw_put(ctx->jdma_device); + atomic_set(&ctx->active, 0); complete_all(&ctx->completion); v4l2_m2m_ctx_release(ctx->m2m_ctx); @@ -774,16 +812,46 @@ static int msm_jpegdma_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) { struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(fh); + struct msm_jpeg_dma_buff __user *up_buff = compat_ptr(buf->m.userptr); + struct msm_jpeg_dma_buff kp_buff; int ret; - mutex_lock(&ctx->lock); + if (!access_ok(VERIFY_READ, up_buff, + sizeof(struct msm_jpeg_dma_buff)) || + get_user(kp_buff.fd, &up_buff->fd) || + get_user(kp_buff.offset, &up_buff->offset)) { + dev_err(ctx->jdma_device->dev, "Error getting user data\n"); + return -EFAULT; + } + + if (!access_ok(VERIFY_WRITE, up_buff, + sizeof(struct msm_jpeg_dma_buff)) || + put_user(kp_buff.fd, &up_buff->fd) || + put_user(kp_buff.offset, &up_buff->offset)) { + dev_err(ctx->jdma_device->dev, "Error putting user data\n"); + return -EFAULT; + } + + switch (buf->type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + ctx->in_offset = kp_buff.offset; + dev_dbg(ctx->jdma_device->dev, "input buf offset %d\n", + ctx->in_offset); + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + ctx->out_offset = kp_buff.offset; + dev_dbg(ctx->jdma_device->dev, "output buf offset %d\n", + ctx->out_offset); + break; + } + + if (atomic_read(&ctx->active)) + ret = msm_jpegdma_update_hw_config(ctx); ret = v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); if (ret < 0) dev_err(ctx->jdma_device->dev, "QBuf fail\n"); - mutex_unlock(&ctx->lock); - return ret; } @@ -816,14 +884,10 @@ static int msm_jpegdma_streamon(struct file *file, if (!msm_jpegdma_config_ok(ctx)) return -EINVAL; - mutex_lock(&ctx->lock); - ret = v4l2_m2m_streamon(file, ctx->m2m_ctx, buf_type); if (ret < 0) dev_err(ctx->jdma_device->dev, "Stream on fail\n"); - mutex_unlock(&ctx->lock); - return ret; } @@ -954,14 +1018,10 @@ static int msm_jpegdma_s_crop(struct file *file, void *fh, if (crop->c.top % formats[ctx->format_idx].v_align) return -EINVAL; - mutex_lock(&ctx->lock); - ctx->crop = crop->c; if (atomic_read(&ctx->active)) ret = msm_jpegdma_update_hw_config(ctx); - mutex_unlock(&ctx->lock); - return ret; } @@ -1004,7 +1064,7 @@ static int msm_jpegdma_s_parm(struct file *file, void *fh, return -EINVAL; if (!a->parm.output.timeperframe.numerator || - !a->parm.output.timeperframe.denominator) + !a->parm.output.timeperframe.denominator) return -EINVAL; /* Frame rate is not supported during streaming */ @@ -1138,16 +1198,15 @@ void msm_jpegdma_isr_processing_done(struct msm_jpegdma_device *dma) struct jpegdma_ctx *ctx; mutex_lock(&dma->lock); + ctx = v4l2_m2m_get_curr_priv(dma->m2m_dev); if (ctx) { - mutex_lock(&ctx->lock); ctx->plane_idx++; if (ctx->plane_idx >= formats[ctx->format_idx].num_planes) { src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); if (src_buf == NULL || dst_buf == NULL) { dev_err(ctx->jdma_device->dev, "Error, buffer list empty\n"); - mutex_unlock(&ctx->lock); mutex_unlock(&dma->lock); return; } @@ -1163,13 +1222,11 @@ void msm_jpegdma_isr_processing_done(struct msm_jpegdma_device *dma) src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); if (src_buf == NULL || dst_buf == NULL) { dev_err(ctx->jdma_device->dev, "Error, buffer list empty\n"); - mutex_unlock(&ctx->lock); mutex_unlock(&dma->lock); return; } msm_jpegdma_process_buffers(ctx, src_buf, dst_buf); } - mutex_unlock(&ctx->lock); } mutex_unlock(&dma->lock); } diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h index adb8b94f098c..0a9cab6e4322 100644 --- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h +++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h @@ -22,7 +22,7 @@ /* Max number of clocks defined in device tree */ #define MSM_JPEGDMA_MAX_CLK 10 /* Core clock index */ -#define MSM_JPEGDMA_CORE_CLK 0 +#define MSM_JPEGDMA_CORE_CLK "core_clk" /* Max number of regulators defined in device tree */ #define MSM_JPEGDMA_MAX_REGULATOR_NUM 3 /* Max number of planes supported */ @@ -109,6 +109,8 @@ struct msm_jpegdma_size_config { struct msm_jpegdma_size out_size; struct msm_jpegdma_format format; unsigned int fps; + unsigned int in_offset; + unsigned int out_offset; }; /* @@ -252,7 +254,6 @@ struct msm_jpegdma_buf_handle { * @format_idx: Current format index. */ struct jpegdma_ctx { - struct mutex lock; struct msm_jpegdma_device *jdma_device; atomic_t active; struct completion completion; @@ -262,6 +263,8 @@ struct jpegdma_ctx { struct v4l2_format format_out; struct v4l2_rect crop; struct v4l2_fract timeperframe; + unsigned int in_offset; + unsigned int out_offset; unsigned int config_idx; struct msm_jpegdma_plane_config plane_config[MSM_JPEGDMA_MAX_CONFIGS]; diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c index 41086936a0b1..e994ce1b8b32 100644 --- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c +++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c @@ -166,6 +166,23 @@ static int msm_jpegdma_hw_get_num_pipes(struct msm_jpegdma_device *dma) } /* + * msm_jpegdma_hw_get_clock_index - Get clock index by name + * @dma: Pointer to dma device. + * @clk_name: clock name. + */ +int msm_jpegdma_hw_get_clock_index(struct msm_jpegdma_device *dma, + const char *clk_name) +{ + uint32_t i = 0; + + for (i = 0; i < dma->num_clk; i++) { + if (!strcmp(clk_name, dma->jpeg_clk_info[i].clk_name)) + return i; + } + return -EINVAL; +} + +/* * msm_jpegdma_hw_reset - Reset jpeg dma core. * @dma: Pointer to dma device. */ @@ -782,12 +799,20 @@ static int msm_jpegdma_hw_calc_speed(struct msm_jpegdma_device *dma, u64 height; u64 real_clock; u64 calc_rate; + int core_clk_idx; width = size->in_size.width + size->in_size.left; height = size->in_size.height + size->in_size.top; calc_rate = (width * height * size->format.depth * size->fps) / 16; - real_clock = clk_round_rate(dma->clk[MSM_JPEGDMA_CORE_CLK], calc_rate); + core_clk_idx = msm_jpegdma_hw_get_clock_index(dma, + MSM_JPEGDMA_CORE_CLK); + if (core_clk_idx < 0) { + dev_err(dma->dev, "Can get clock index for dma %s\n", + MSM_JPEGDMA_CORE_CLK); + } + + real_clock = clk_round_rate(dma->clk[core_clk_idx], calc_rate); if (real_clock < 0) { dev_err(dma->dev, "Can not round core clock\n"); return -EINVAL; @@ -817,6 +842,7 @@ static int msm_jpegdma_hw_set_speed(struct msm_jpegdma_device *dma, struct msm_jpegdma_speed new_sp; struct msm_jpegdma_size_config new_size; int ret; + int core_clk_idx; if (dma->active_clock_rate >= speed->core_clock) return 0; @@ -830,7 +856,14 @@ static int msm_jpegdma_hw_set_speed(struct msm_jpegdma_device *dma, return -EINVAL; } - ret = clk_set_rate(dma->clk[MSM_JPEGDMA_CORE_CLK], new_sp.core_clock); + core_clk_idx = msm_jpegdma_hw_get_clock_index(dma, + MSM_JPEGDMA_CORE_CLK); + if (core_clk_idx < 0) { + dev_err(dma->dev, "Can get clock index for dma %s\n", + MSM_JPEGDMA_CORE_CLK); + } + + ret = clk_set_rate(dma->clk[core_clk_idx], new_sp.core_clock); if (ret < 0) { dev_err(dma->dev, "Fail Core clock rate %d\n", ret); return -EINVAL; @@ -1022,13 +1055,20 @@ int msm_jpegdma_hw_set_config(struct msm_jpegdma_device *dma, plane_cfg->plane[0].active_pipes = dma->hw_num_pipes; plane_cfg->plane[0].type = size_cfg->format.planes[0]; msm_jpegdma_hw_calc_config(size_cfg, &plane_cfg->plane[0]); + + in_offset = size_cfg->in_offset; + out_offset = size_cfg->out_offset; + + msm_jpegdma_hw_add_plane_offset(&plane_cfg->plane[0], + in_offset, out_offset); + if (size_cfg->format.num_planes == 1) return 0; - in_offset = size_cfg->in_size.scanline * - size_cfg->in_size.stride; - out_offset = size_cfg->out_size.scanline * - size_cfg->out_size.stride; + in_offset += (size_cfg->in_size.scanline * + size_cfg->in_size.stride); + out_offset += (size_cfg->out_size.scanline * + size_cfg->out_size.stride); memset(&plane_size, 0x00, sizeof(plane_size)); for (i = 1; i < size_cfg->format.num_planes; i++) { @@ -1336,7 +1376,8 @@ int msm_jpegdma_hw_get_qos(struct msm_jpegdma_device *dma) unsigned int cnt; const void *property; - property = of_get_property(dma->dev->of_node, "qcom,qos-regs", &cnt); + property = of_get_property(dma->dev->of_node, + "qcom,qos-reg-settings", &cnt); if (!property || !cnt) { dev_dbg(dma->dev, "Missing qos settings\n"); return 0; @@ -1347,9 +1388,9 @@ int msm_jpegdma_hw_get_qos(struct msm_jpegdma_device *dma) if (!dma->qos_regs) return -ENOMEM; - for (i = 0; i < cnt; i++) { + for (i = 0; i < cnt; i = i + 2) { ret = of_property_read_u32_index(dma->dev->of_node, - "qcom,qos-regs", i, + "qcom,qos-reg-settings", i, &dma->qos_regs[i].reg); if (ret < 0) { dev_err(dma->dev, "can not read qos reg %d\n", i); @@ -1357,7 +1398,7 @@ int msm_jpegdma_hw_get_qos(struct msm_jpegdma_device *dma) } ret = of_property_read_u32_index(dma->dev->of_node, - "qcom,qos-settings", i, + "qcom,qos-reg-settings", i + 1, &dma->qos_regs[i].val); if (ret < 0) { dev_err(dma->dev, "can not read qos setting %d\n", i); @@ -1397,7 +1438,8 @@ int msm_jpegdma_hw_get_vbif(struct msm_jpegdma_device *dma) unsigned int cnt; const void *property; - property = of_get_property(dma->dev->of_node, "qcom,vbif-regs", &cnt); + property = of_get_property(dma->dev->of_node, "qcom,vbif-reg-settings", + &cnt); if (!property || !cnt) { dev_dbg(dma->dev, "Missing vbif settings\n"); return 0; @@ -1408,9 +1450,9 @@ int msm_jpegdma_hw_get_vbif(struct msm_jpegdma_device *dma) if (!dma->vbif_regs) return -ENOMEM; - for (i = 0; i < cnt; i++) { + for (i = 0; i < cnt; i = i + 2) { ret = of_property_read_u32_index(dma->dev->of_node, - "qcom,vbif-regs", i, + "qcom,vbif-reg-settings", i, &dma->vbif_regs[i].reg); if (ret < 0) { dev_err(dma->dev, "can not read vbif reg %d\n", i); @@ -1418,7 +1460,7 @@ int msm_jpegdma_hw_get_vbif(struct msm_jpegdma_device *dma) } ret = of_property_read_u32_index(dma->dev->of_node, - "qcom,vbif-settings", i, + "qcom,vbif-reg-settings", i + 1, &dma->vbif_regs[i].val); if (ret < 0) { dev_err(dma->dev, "can not read vbif setting %d\n", i); @@ -1459,8 +1501,8 @@ int msm_jpegdma_hw_get_prefetch(struct msm_jpegdma_device *dma) unsigned int cnt; const void *property; - property = of_get_property(dma->dev->of_node, "qcom,prefetch-regs", - &cnt); + property = of_get_property(dma->dev->of_node, + "qcom,prefetch-reg-settings", &cnt); if (!property || !cnt) { dev_dbg(dma->dev, "Missing prefetch settings\n"); return 0; @@ -1472,9 +1514,9 @@ int msm_jpegdma_hw_get_prefetch(struct msm_jpegdma_device *dma) if (!dma->prefetch_regs) return -ENOMEM; - for (i = 0; i < cnt; i++) { + for (i = 0; i < cnt; i = i + 2) { ret = of_property_read_u32_index(dma->dev->of_node, - "qcom,prefetch-regs", i, + "qcom,prefetch-reg-settings", i, &dma->prefetch_regs[i].reg); if (ret < 0) { dev_err(dma->dev, "can not read prefetch reg %d\n", i); @@ -1482,7 +1524,7 @@ int msm_jpegdma_hw_get_prefetch(struct msm_jpegdma_device *dma) } ret = of_property_read_u32_index(dma->dev->of_node, - "qcom,prefetch-settings", i, + "qcom,prefetch-reg-settings", i + 1, &dma->prefetch_regs[i].val); if (ret < 0) { dev_err(dma->dev, "can not read prefetch setting %d\n", @@ -1598,6 +1640,9 @@ int msm_jpegdma_hw_get(struct msm_jpegdma_device *dma) msm_jpegdma_hw_config_qos(dma); msm_jpegdma_hw_config_vbif(dma); + msm_camera_register_threaded_irq(dma->pdev, dma->irq, NULL, + msm_jpegdma_hw_irq, IRQF_ONESHOT | IRQF_TRIGGER_RISING, + dev_name(&dma->pdev->dev), dma); msm_jpegdma_hw_enable_irq(dma); ret = msm_jpegdma_hw_reset(dma); @@ -1710,6 +1755,7 @@ error: static void msm_jpegdma_hw_detach_iommu(struct msm_jpegdma_device *dma) { mutex_lock(&dma->lock); + if (dma->iommu_attached_cnt == 0) { dev_err(dma->dev, "There is no attached device\n"); mutex_unlock(&dma->lock); @@ -1720,6 +1766,7 @@ static void msm_jpegdma_hw_detach_iommu(struct msm_jpegdma_device *dma) cam_smmu_ops(dma->iommu_hndl, CAM_SMMU_DETACH); cam_smmu_destroy_handle(dma->iommu_hndl); } + mutex_unlock(&dma->lock); } diff --git a/drivers/platform/msm/msm_11ad/msm_11ad.c b/drivers/platform/msm/msm_11ad/msm_11ad.c index 203e0c4b4339..a8adc2401dbf 100644 --- a/drivers/platform/msm/msm_11ad/msm_11ad.c +++ b/drivers/platform/msm/msm_11ad/msm_11ad.c @@ -572,6 +572,7 @@ static int msm_11ad_smmu_init(struct msm11ad_ctx *ctx) int disable_htw = 1; int atomic_ctx = 1; int rc; + int bypass_enable = 1; if (!ctx->use_smmu) return 0; @@ -605,6 +606,15 @@ static int msm_11ad_smmu_init(struct msm11ad_ctx *ctx) goto release_mapping; } + rc = iommu_domain_set_attr(ctx->mapping->domain, + DOMAIN_ATTR_S1_BYPASS, + &bypass_enable); + if (rc) { + dev_err(ctx->dev, "Set bypass attribute to SMMU failed (%d)\n", + rc); + goto release_mapping; + } + rc = arm_iommu_attach_device(&ctx->pcidev->dev, ctx->mapping); if (rc) { dev_err(ctx->dev, "arm_iommu_attach_device failed (%d)\n", rc); diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index b6e2a55d5a9e..ba135e354ace 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -427,6 +427,25 @@ config MSM_GLADIATOR_ERP If unsure, say N. +config MSM_GLADIATOR_ERP_V2 + tristate "GLADIATOR coherency interconnect error reporting driver v2" + help + Support dumping debug information for the GLADIATOR + cache interconnect in the error interrupt handler. + Meant to be used for debug scenarios only. + + If unsure, say N. + +config PANIC_ON_GLADIATOR_ERROR_V2 + depends on MSM_GLADIATOR_ERP_V2 + bool "Panic on GLADIATOR error report v2" + help + Panic upon detection of an Gladiator coherency interconnect error + in order to support dumping debug information. + Meant to be used for debug scenarios only. + + If unsure, say N. + config MSM_GLADIATOR_HANG_DETECT tristate "MSM Gladiator Hang Detection Support" help diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 1a4757f16e77..2433e81a831b 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -74,6 +74,7 @@ obj-$(CONFIG_MSM_MPM_OF) += mpm-of.o obj-$(CONFIG_MSM_EVENT_TIMER) += event_timer.o obj-$(CONFIG_MSM_TZ_SMMU) += msm_tz_smmu.o obj-$(CONFIG_MSM_GLADIATOR_ERP) += gladiator_erp.o +obj-$(CONFIG_MSM_GLADIATOR_ERP_V2) += gladiator_erp_v2.o obj-$(CONFIG_MSM_CORE_HANG_DETECT) += core_hang_detect.o obj-$(CONFIG_MSM_GLADIATOR_HANG_DETECT) += gladiator_hang_detect.o obj-$(CONFIG_MSM_RUN_QUEUE_STATS) += msm_rq_stats.o diff --git a/drivers/soc/qcom/gladiator_erp_v2.c b/drivers/soc/qcom/gladiator_erp_v2.c new file mode 100644 index 000000000000..70aace270acf --- /dev/null +++ b/drivers/soc/qcom/gladiator_erp_v2.c @@ -0,0 +1,799 @@ +/* Copyright (c) 2015-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 <linux/module.h> +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/cpu_pm.h> +#include <linux/platform_device.h> +#include <soc/qcom/scm.h> +#include <linux/of.h> +#include <linux/clk.h> + +#define MODULE_NAME "gladiator-v2_error_reporting" + +/* Register Offsets */ +#define GLADIATOR_ID_COREID 0x0 +#define GLADIATOR_ID_REVISIONID 0x4 +#define GLADIATOR_FAULTEN 0x1010 +#define GLADIATOR_ERRVLD 0x1014 +#define GLADIATOR_ERRCLR 0x1018 +#define GLADIATOR_ERRLOG0 0x101C +#define GLADIATOR_ERRLOG1 0x1020 +#define GLADIATOR_ERRLOG2 0x1024 +#define GLADIATOR_ERRLOG3 0x1028 +#define GLADIATOR_ERRLOG4 0x102C +#define GLADIATOR_ERRLOG5 0x1030 +#define GLADIATOR_ERRLOG6 0x1034 +#define GLADIATOR_ERRLOG7 0x1038 +#define GLADIATOR_ERRLOG8 0x103C +#define OBSERVER_0_ID_COREID 0x8000 +#define OBSERVER_0_FAULTEN 0x8008 +#define OBSERVER_0_ERRVLD 0x800C +#define OBSERVER_0_ERRCLR 0x8010 +#define OBSERVER_0_ERRLOG0 0x8014 +#define OBSERVER_0_ERRLOG1 0x8018 +#define OBSERVER_0_ERRLOG2 0x801C +#define OBSERVER_0_ERRLOG3 0x8020 +#define OBSERVER_0_ERRLOG4 0x8024 +#define OBSERVER_0_ERRLOG5 0x8028 +#define OBSERVER_0_ERRLOG6 0x802C +#define OBSERVER_0_ERRLOG7 0x8030 +#define OBSERVER_0_ERRLOG8 0x8034 +#define OBSERVER_0_STALLEN 0x8038 +#define OBSERVER_0_REVISIONID 0x8004 + +#define GLD_TRANS_OPCODE_MASK 0xE +#define GLD_TRANS_OPCODE_SHIFT 1 +#define GLD_ERROR_TYPE_MASK 0x700 +#define GLD_ERROR_TYPE_SHIFT 8 +#define GLD_LEN1_MASK 0xFFF0000 +#define GLD_LEN1_SHIFT 16 +#define GLD_TRANS_SOURCEID_MASK 0x7 +#define GLD_TRANS_SOURCEID_SHIFT 0 +#define GLD_TRANS_TARGETID_MASK 0x7 +#define GLD_TRANS_TARGETID_SHIFT 0 +#define GLD_ERRLOG_ERROR 0x7 +#define GLD_ERRLOG5_ERROR_TYPE_MASK 0xFF000000 +#define GLD_ERRLOG5_ERROR_TYPE_SHIFT 24 +#define GLD_ACE_PORT_PARITY_MASK 0xc000 +#define GLD_ACE_PORT_PARITY_SHIFT 14 +#define GLD_ACE_PORT_DISCONNECT_MASK 0xf0000 +#define GLD_ACE_PORT_DISCONNECT_SHIFT 16 +#define GLD_ACE_PORT_DIRECTORY_MASK 0xf00000 +#define GLD_ACE_PORT_DIRECTORY_SHIFT 20 +#define GLD_INDEX_PARITY_MASK 0x1FFF +#define GLD_INDEX_PARITY_SHIFT 0 +#define OBS_TRANS_OPCODE_MASK 0x1E +#define OBS_TRANS_OPCODE_SHIFT 1 +#define OBS_ERROR_TYPE_MASK 0x700 +#define OBS_ERROR_TYPE_SHIFT 8 +#define OBS_LEN1_MASK 0x7F0000 +#define OBS_LEN1_SHIFT 16 + +struct msm_gladiator_data { + void __iomem *gladiator_virt_base; + int erp_irq; + struct notifier_block pm_notifier_block; + struct clk *qdss_clk; +}; + +static int enable_panic_on_error; +module_param(enable_panic_on_error, int, 0); + +enum gld_trans_opcode { + GLD_RD, + GLD_RDX, + GLD_RDL, + GLD_RESERVED, + GLD_WR, + GLD_WRC, + GLD_PRE, +}; + +enum obs_trans_opcode { + OBS_RD, + OBS_RDW, + OBS_RDL, + OBS_RDX, + OBS_WR, + OBS_WRW, + OBS_WRC, + OBS_RESERVED, + OBS_PRE, + OBS_URG, +}; + +enum obs_err_code { + OBS_SLV, + OBS_DEC, + OBS_UNS, + OBS_DISC, + OBS_SEC, + OBS_HIDE, + OBS_TMO, + OBS_RSV, +}; + +enum err_log { + ERR_LOG0, + ERR_LOG1, + ERR_LOG2, + ERR_LOG3, + ERR_LOG4, + ERR_LOG5, + ERR_LOG6, + ERR_LOG7, + ERR_LOG8, + STALLEN, +}; + +enum type_logger_error { + DATA_TRANSFER_ERROR, + DVM_ERROR, + TX_ERROR, + TXR_ERROR, + DISCONNECT_ERROR, + DIRECTORY_ERROR, + PARITY_ERROR, +}; + +static void clear_gladiator_error(void __iomem *gladiator_virt_base) +{ + writel_relaxed(1, gladiator_virt_base + GLADIATOR_ERRCLR); + writel_relaxed(1, gladiator_virt_base + OBSERVER_0_ERRCLR); +} + +static inline void print_gld_transaction(unsigned int opc) +{ + switch (opc) { + case GLD_RD: + pr_alert("Transaction type: READ\n"); + break; + case GLD_RDX: + pr_alert("Transaction type: EXCLUSIVE READ\n"); + break; + case GLD_RDL: + pr_alert("Transaction type: LINKED READ\n"); + break; + case GLD_WR: + pr_alert("Transaction type: WRITE\n"); + break; + case GLD_WRC: + pr_alert("Transaction type: CONDITIONAL WRITE\n"); + break; + case GLD_PRE: + pr_alert("Transaction: Preamble packet of linked sequence\n"); + break; + default: + pr_alert("Transaction type: Unknown; value:%u\n", opc); + } +} + +static inline void print_gld_errtype(unsigned int errtype) +{ + if (errtype == 0) + pr_alert("Error type: Snoop data transfer\n"); + else if (errtype == 1) + pr_alert("Error type: DVM error\n"); + else if (errtype == 3) + pr_alert("Error type: Disconnect, directory, or parity error\n"); + else + pr_alert("Error type: Unknown; value:%u\n", errtype); +} + +static void decode_gld_errlog0(u32 err_reg) +{ + unsigned int opc, errtype, len1; + + opc = (err_reg & GLD_TRANS_OPCODE_MASK) >> GLD_TRANS_OPCODE_SHIFT; + errtype = (err_reg & GLD_ERROR_TYPE_MASK) >> GLD_ERROR_TYPE_SHIFT; + len1 = (err_reg & GLD_LEN1_MASK) >> GLD_LEN1_SHIFT; + + print_gld_transaction(opc); + print_gld_errtype(errtype); + pr_alert("number of payload bytes: %d\n", len1 + 1); +} + +static void decode_gld_errlog1(u32 err_reg) +{ + if ((err_reg & GLD_ERRLOG_ERROR) == GLD_ERRLOG_ERROR) + pr_alert("Transaction issued on IO target generic interface\n"); + else + pr_alert("Transaction source ID: %d\n", + (err_reg & GLD_TRANS_SOURCEID_MASK) + >> GLD_TRANS_SOURCEID_SHIFT); +} + +static void decode_gld_errlog2(u32 err_reg) +{ + if ((err_reg & GLD_ERRLOG_ERROR) == GLD_ERRLOG_ERROR) + pr_alert("Error response coming from: external DVM network\n"); + else + pr_alert("Error response coming from: Target ID: %d\n", + (err_reg & GLD_TRANS_TARGETID_MASK) + >> GLD_TRANS_TARGETID_SHIFT); +} + +static void decode_ace_port_index(u32 type, u32 error) +{ + unsigned port; + + switch (type) { + case DISCONNECT_ERROR: + port = (error & GLD_ACE_PORT_DISCONNECT_MASK) + >> GLD_ACE_PORT_DISCONNECT_SHIFT; + pr_alert("ACE port index: %d\n", port); + break; + case DIRECTORY_ERROR: + port = (error & GLD_ACE_PORT_DIRECTORY_MASK) + >> GLD_ACE_PORT_DIRECTORY_SHIFT; + pr_alert("ACE port index: %d\n", port); + break; + case PARITY_ERROR: + port = (error & GLD_ACE_PORT_PARITY_MASK) + >> GLD_ACE_PORT_PARITY_SHIFT; + pr_alert("ACE port index: %d\n", port); + } +} + +static void decode_index_parity(u32 error) +{ + pr_alert("Index: %d\n", + (error & GLD_INDEX_PARITY_MASK) + >> GLD_INDEX_PARITY_SHIFT); +} + +static void decode_gld_logged_error(u32 err_reg5) +{ + unsigned int log_err_type, i, value; + + log_err_type = (err_reg5 & GLD_ERRLOG5_ERROR_TYPE_MASK) + >> GLD_ERRLOG5_ERROR_TYPE_SHIFT; + for (i = 0 ; i <= 6 ; i++) { + value = log_err_type & 0x1; + switch (i) { + case DATA_TRANSFER_ERROR: + if (value == 0) + continue; + pr_alert("Error type: Data transfer error\n"); + break; + case DVM_ERROR: + if (value == 0) + continue; + pr_alert("Error type: DVM error\n"); + break; + case TX_ERROR: + if (value == 0) + continue; + pr_alert("Error type: Tx error\n"); + break; + case TXR_ERROR: + if (value == 0) + continue; + pr_alert("Error type: TxR error\n"); + break; + case DISCONNECT_ERROR: + if (value == 0) + continue; + pr_alert("Error type: Disconnect error\n"); + decode_ace_port_index( + DISCONNECT_ERROR, + err_reg5); + break; + case DIRECTORY_ERROR: + if (value == 0) + continue; + pr_alert("Error type: Directory error\n"); + decode_ace_port_index( + DIRECTORY_ERROR, + err_reg5); + break; + case PARITY_ERROR: + if (value == 0) + continue; + pr_alert("Error type: Parity error\n"); + decode_ace_port_index(PARITY_ERROR, err_reg5); + decode_index_parity(err_reg5); + break; + } + log_err_type = log_err_type >> 1; + } +} + +static void decode_gld_errlog(u32 err_reg, unsigned int err_log) +{ + switch (err_log) { + case ERR_LOG0: + decode_gld_errlog0(err_reg); + break; + case ERR_LOG1: + decode_gld_errlog1(err_reg); + break; + case ERR_LOG2: + decode_gld_errlog2(err_reg); + break; + case ERR_LOG3: + pr_alert("Lower 32-bits of error address: %08x\n", err_reg); + break; + case ERR_LOG4: + pr_alert("Upper 32-bits of error address: %08x\n", err_reg); + break; + case ERR_LOG5: + pr_alert("Lower 32-bits of user: %08x\n", err_reg); + break; + case ERR_LOG6: + pr_alert("Mid 32-bits(63-32) of user: %08x\n", err_reg); + break; + case ERR_LOG7: + break; + case ERR_LOG8: + pr_alert("Upper 32-bits(95-64) of user: %08x\n", err_reg); + break; + default: + pr_alert("Invalid error register; reg num:%u\n", err_log); + } +} + +static inline void print_obs_transaction(unsigned int opc) +{ + switch (opc) { + case OBS_RD: + pr_alert("Transaction type: READ\n"); + break; + case OBS_RDW: + pr_alert("Transaction type: WRAPPED READ\n"); + break; + case OBS_RDL: + pr_alert("Transaction type: LINKED READ\n"); + break; + case OBS_RDX: + pr_alert("Transaction type: EXCLUSIVE READ\n"); + break; + case OBS_WR: + pr_alert("Transaction type: WRITE\n"); + break; + case OBS_WRW: + pr_alert("Transaction type: WRAPPED WRITE\n"); + break; + case OBS_WRC: + pr_alert("Transaction type: CONDITIONAL WRITE\n"); + break; + case OBS_PRE: + pr_alert("Transaction: Preamble packet of linked sequence\n"); + break; + case OBS_URG: + pr_alert("Transaction type: Urgency Packet\n"); + break; + default: + pr_alert("Transaction type: Unknown; value:%u\n", opc); + } +} + +static inline void print_obs_errcode(unsigned int errcode) +{ + switch (errcode) { + case OBS_SLV: + pr_alert("Error code: Target error detected by slave\n"); + pr_alert("Source: Target\n"); + break; + case OBS_DEC: + pr_alert("Error code: Address decode error\n"); + pr_alert("Source: Initiator NIU\n"); + break; + case OBS_UNS: + pr_alert("Error code: Unsupported request\n"); + pr_alert("Source: Target NIU\n"); + break; + case OBS_DISC: + pr_alert("Error code: Disconnected target or domain\n"); + pr_alert("Source: Power Disconnect\n"); + break; + case OBS_SEC: + pr_alert("Error code: Security violation\n"); + pr_alert("Source: Initiator NIU or Firewall\n"); + break; + case OBS_HIDE: + pr_alert("Error :Hidden security violation, reported as OK\n"); + pr_alert("Source: Firewall\n"); + break; + case OBS_TMO: + pr_alert("Error code: Time-out\n"); + pr_alert("Source: Target NIU\n"); + break; + default: + pr_alert("Error code: Unknown; code:%u\n", errcode); + } +} + +static void decode_obs_errlog0(u32 err_reg) +{ + unsigned int opc, errcode, len1; + + opc = (err_reg & OBS_TRANS_OPCODE_MASK) >> OBS_TRANS_OPCODE_SHIFT; + errcode = (err_reg & OBS_ERROR_TYPE_MASK) >> OBS_ERROR_TYPE_SHIFT; + len1 = (err_reg & OBS_LEN1_MASK) >> OBS_LEN1_SHIFT; + + print_obs_transaction(opc); + print_obs_errcode(errcode); + pr_alert("number of payload bytes: %d\n", len1 + 1); +} + +static void decode_obs_errlog(u32 err_reg, unsigned int err_log) +{ + switch (err_log) { + case ERR_LOG0: + decode_obs_errlog0(err_reg); + break; + case ERR_LOG1: + pr_alert("RouteId of the error: %08x\n", err_reg); + break; + case ERR_LOG2: + /* reserved error log register */ + break; + case ERR_LOG3: + pr_alert("Lower 32-bits of error address: %08x\n", err_reg); + break; + case ERR_LOG4: + pr_alert("Upper 12-bits of error address: %08x\n", err_reg); + break; + case ERR_LOG5: + pr_alert("Lower 13-bits of user: %08x\n", err_reg); + break; + case ERR_LOG6: + /* reserved error log register */ + break; + case ERR_LOG7: + pr_alert("Security filed of the logged error: %08x\n", err_reg); + break; + case ERR_LOG8: + /* reserved error log register */ + break; + case STALLEN: + pr_alert("stall mode of the error logger: %08x\n", + err_reg & 0x1); + break; + default: + pr_alert("Invalid error register; reg num:%u\n", err_log); + } +} + +static u32 get_gld_offset(unsigned int err_log) +{ + u32 offset = 0; + + switch (err_log) { + case ERR_LOG0: + offset = GLADIATOR_ERRLOG0; + break; + case ERR_LOG1: + offset = GLADIATOR_ERRLOG1; + break; + case ERR_LOG2: + offset = GLADIATOR_ERRLOG2; + break; + case ERR_LOG3: + offset = GLADIATOR_ERRLOG3; + break; + case ERR_LOG4: + offset = GLADIATOR_ERRLOG4; + break; + case ERR_LOG5: + offset = GLADIATOR_ERRLOG5; + break; + case ERR_LOG6: + offset = GLADIATOR_ERRLOG6; + break; + case ERR_LOG7: + offset = GLADIATOR_ERRLOG7; + break; + case ERR_LOG8: + offset = GLADIATOR_ERRLOG8; + break; + default: + pr_alert("Invalid gladiator error register; reg num:%u\n", + err_log); + } + return offset; +} + +static u32 get_obs_offset(unsigned int err_log) +{ + u32 offset = 0; + + switch (err_log) { + case ERR_LOG0: + offset = OBSERVER_0_ERRLOG0; + break; + case ERR_LOG1: + offset = OBSERVER_0_ERRLOG1; + break; + case ERR_LOG2: + offset = OBSERVER_0_ERRLOG2; + break; + case ERR_LOG3: + offset = OBSERVER_0_ERRLOG3; + break; + case ERR_LOG4: + offset = OBSERVER_0_ERRLOG4; + break; + case ERR_LOG5: + offset = OBSERVER_0_ERRLOG5; + break; + case ERR_LOG6: + offset = OBSERVER_0_ERRLOG6; + break; + case ERR_LOG7: + offset = OBSERVER_0_ERRLOG7; + break; + case ERR_LOG8: + offset = OBSERVER_0_ERRLOG8; + break; + case STALLEN: + offset = OBSERVER_0_STALLEN; + break; + default: + pr_alert("Invalid observer error register; reg num:%u\n", + err_log); + } + return offset; +} + +static void decode_gld_errlog5(struct msm_gladiator_data *msm_gld_data) +{ + unsigned int errtype; + u32 err_reg0, err_reg5; + + err_reg0 = readl_relaxed(msm_gld_data->gladiator_virt_base + + get_gld_offset(ERR_LOG0)); + err_reg5 = readl_relaxed(msm_gld_data->gladiator_virt_base + + get_gld_offset(ERR_LOG5)); + + errtype = (err_reg0 & GLD_ERROR_TYPE_MASK) >> GLD_ERROR_TYPE_SHIFT; + if (errtype == 3) + decode_gld_logged_error(err_reg5); + else if (errtype == 0 || errtype == 1) + pr_alert("Lower 32-bits of user: %08x\n", err_reg5); + else + pr_alert("Error type: Unknown; value:%u\n", errtype); +} + +static irqreturn_t msm_gladiator_isr(int irq, void *dev_id) +{ + u32 err_reg; + unsigned int err_log; + + struct msm_gladiator_data *msm_gld_data = dev_id; + + /* Check validity */ + bool gld_err_valid = readl_relaxed(msm_gld_data->gladiator_virt_base + + GLADIATOR_ERRVLD); + + bool obsrv_err_valid = readl_relaxed( + msm_gld_data->gladiator_virt_base + OBSERVER_0_ERRVLD); + + if (!gld_err_valid && !obsrv_err_valid) { + pr_err("%s Invalid Gladiator error reported, clear it\n", + __func__); + /* Clear IRQ */ + clear_gladiator_error(msm_gld_data->gladiator_virt_base); + return IRQ_HANDLED; + } + pr_alert("GLADIATOR ERROR DETECTED\n"); + if (gld_err_valid) { + pr_alert("GLADIATOR error log register data:\n"); + for (err_log = ERR_LOG0; err_log <= ERR_LOG8; err_log++) { + /* skip log register 7 as its reserved */ + if (err_log == ERR_LOG7) + continue; + if (err_log == ERR_LOG5) { + decode_gld_errlog5(msm_gld_data); + continue; + } + err_reg = readl_relaxed( + msm_gld_data->gladiator_virt_base + + get_gld_offset(err_log)); + decode_gld_errlog(err_reg, err_log); + } + } + if (obsrv_err_valid) { + pr_alert("Observor error log register data:\n"); + for (err_log = ERR_LOG0; err_log <= STALLEN; err_log++) { + /* skip log register 2, 6 and 8 as they are reserved */ + if ((err_log == ERR_LOG2) || (err_log == ERR_LOG6) + || (err_log == ERR_LOG8)) + continue; + err_reg = readl_relaxed( + msm_gld_data->gladiator_virt_base + + get_obs_offset(err_log)); + decode_obs_errlog(err_reg, err_log); + } + } + /* Clear IRQ */ + clear_gladiator_error(msm_gld_data->gladiator_virt_base); + if (enable_panic_on_error) + panic("Gladiator Cache Interconnect Error Detected!\n"); + else + WARN(1, "Gladiator Cache Interconnect Error Detected\n"); + + return IRQ_HANDLED; +} + +static const struct of_device_id gladiator_erp_v2_match_table[] = { + { .compatible = "qcom,msm-gladiator-v2" }, + {}, +}; + +static int parse_dt_node(struct platform_device *pdev, + struct msm_gladiator_data *msm_gld_data) +{ + int ret = 0; + struct resource *res; + + res = platform_get_resource_byname(pdev, + IORESOURCE_MEM, "gladiator_base"); + if (!res) + return -ENODEV; + if (!devm_request_mem_region(&pdev->dev, res->start, + resource_size(res), + "msm-gladiator-erp")) { + + dev_err(&pdev->dev, "%s cannot reserve gladiator erp region\n", + __func__); + return -ENXIO; + } + msm_gld_data->gladiator_virt_base = devm_ioremap(&pdev->dev, + res->start, resource_size(res)); + if (!msm_gld_data->gladiator_virt_base) { + dev_err(&pdev->dev, "%s cannot map gladiator register space\n", + __func__); + return -ENXIO; + } + msm_gld_data->erp_irq = platform_get_irq(pdev, 0); + if (!msm_gld_data->erp_irq) + return -ENODEV; + + /* clear existing errors before enabling the interrupt */ + clear_gladiator_error(msm_gld_data->gladiator_virt_base); + ret = devm_request_irq(&pdev->dev, msm_gld_data->erp_irq, + msm_gladiator_isr, IRQF_TRIGGER_HIGH, + "gladiator-error", msm_gld_data); + if (ret) + dev_err(&pdev->dev, "Failed to register irq handler\n"); + + return ret; +} + +static inline void gladiator_irq_init(void __iomem *gladiator_virt_base) +{ + writel_relaxed(1, gladiator_virt_base + GLADIATOR_FAULTEN); + writel_relaxed(1, gladiator_virt_base + OBSERVER_0_FAULTEN); +} + +#define CCI_LEVEL 2 +static int gladiator_erp_pm_callback(struct notifier_block *nb, + unsigned long val, void *data) +{ + unsigned int level = (unsigned long) data; + struct msm_gladiator_data *msm_gld_data = container_of(nb, + struct msm_gladiator_data, pm_notifier_block); + + if (level != CCI_LEVEL) + return NOTIFY_DONE; + + switch (val) { + case CPU_CLUSTER_PM_EXIT: + gladiator_irq_init(msm_gld_data->gladiator_virt_base); + break; + default: + return NOTIFY_DONE; + } + + return NOTIFY_OK; +} + +static int gladiator_erp_v2_probe(struct platform_device *pdev) +{ + int ret; + struct msm_gladiator_data *msm_gld_data; + + msm_gld_data = devm_kzalloc(&pdev->dev, + sizeof(struct msm_gladiator_data), GFP_KERNEL); + if (!msm_gld_data) { + ret = -ENOMEM; + goto bail; + } + + ret = parse_dt_node(pdev, msm_gld_data); + if (ret) + goto bail; + msm_gld_data->pm_notifier_block.notifier_call = + gladiator_erp_pm_callback; + + if (of_property_match_string(pdev->dev.of_node, + "clock-names", "atb_clk") >= 0) { + msm_gld_data->qdss_clk = devm_clk_get(&pdev->dev, "atb_clk"); + if (IS_ERR(msm_gld_data->qdss_clk)) { + dev_err(&pdev->dev, "Failed to get QDSS ATB clock\n"); + goto bail; + } + } else { + dev_err(&pdev->dev, "No matching string of QDSS ATB clock\n"); + goto bail; + } + + ret = clk_prepare_enable(msm_gld_data->qdss_clk); + if (ret) + goto err_atb_clk; + + gladiator_irq_init(msm_gld_data->gladiator_virt_base); + platform_set_drvdata(pdev, msm_gld_data); + cpu_pm_register_notifier(&msm_gld_data->pm_notifier_block); +#ifdef CONFIG_PANIC_ON_GLADIATOR_ERROR_V2 + enable_panic_on_error = 1; +#endif + dev_info(&pdev->dev, "MSM Gladiator Error Reporting V2 Initialized\n"); + return ret; + +err_atb_clk: + clk_disable_unprepare(msm_gld_data->qdss_clk); + +bail: + dev_err(&pdev->dev, "Probe failed bailing out\n"); + return ret; +} + +static int gladiator_erp_v2_remove(struct platform_device *pdev) +{ + struct msm_gladiator_data *msm_gld_data = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + cpu_pm_unregister_notifier(&msm_gld_data->pm_notifier_block); + clk_disable_unprepare(msm_gld_data->qdss_clk); + return 0; +} + +static struct platform_driver gladiator_erp_driver = { + .probe = gladiator_erp_v2_probe, + .remove = gladiator_erp_v2_remove, + .driver = { + .name = MODULE_NAME, + .owner = THIS_MODULE, + .of_match_table = gladiator_erp_v2_match_table, + }, +}; + +static int __init init_gladiator_erp_v2(void) +{ + int ret; + + ret = scm_is_secure_device(); + if (ret == 0) { + pr_info("Gladiator Error Reporting not available\n"); + return -ENODEV; + } + + return platform_driver_register(&gladiator_erp_driver); +} +module_init(init_gladiator_erp_v2); + +static void __exit exit_gladiator_erp_v2(void) +{ + return platform_driver_unregister(&gladiator_erp_driver); +} +module_exit(exit_gladiator_erp_v2); + +MODULE_DESCRIPTION("Gladiator Error Reporting V2"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c index aad67abc709a..388fb70604b6 100644 --- a/drivers/soc/qcom/glink.c +++ b/drivers/soc/qcom/glink.c @@ -4338,6 +4338,9 @@ static bool ch_migrate(struct channel_ctx *l_ctx, struct channel_ctx *r_ctx) list_del_init(&l_ctx->port_list_node); spin_unlock_irqrestore(&l_ctx->transport_ptr->xprt_ctx_lock_lhb1, flags); + mutex_lock(&l_ctx->transport_ptr->xprt_dbgfs_lock_lhb3); + glink_debugfs_remove_channel(l_ctx, l_ctx->transport_ptr); + mutex_unlock(&l_ctx->transport_ptr->xprt_dbgfs_lock_lhb3); memcpy(ctx_clone, l_ctx, sizeof(*ctx_clone)); ctx_clone->local_xprt_req = 0; @@ -4372,11 +4375,13 @@ static bool ch_migrate(struct channel_ctx *l_ctx, struct channel_ctx *r_ctx) l_ctx->transport_ptr = xprt; l_ctx->local_xprt_req = 0; l_ctx->local_xprt_resp = 0; - if (new_xprt != r_ctx->transport_ptr->id) { - r_ctx->local_xprt_req = 0; - r_ctx->local_xprt_resp = 0; - r_ctx->remote_xprt_req = 0; - r_ctx->remote_xprt_resp = 0; + if (new_xprt != r_ctx->transport_ptr->id || l_ctx == r_ctx) { + if (new_xprt != r_ctx->transport_ptr->id) { + r_ctx->local_xprt_req = 0; + r_ctx->local_xprt_resp = 0; + r_ctx->remote_xprt_req = 0; + r_ctx->remote_xprt_resp = 0; + } l_ctx->remote_xprt_req = 0; l_ctx->remote_xprt_resp = 0; @@ -4409,6 +4414,9 @@ static bool ch_migrate(struct channel_ctx *l_ctx, struct channel_ctx *r_ctx) spin_unlock_irqrestore(&xprt->xprt_ctx_lock_lhb1, flags); } + mutex_lock(&xprt->xprt_dbgfs_lock_lhb3); + glink_debugfs_add_channel(l_ctx, xprt); + mutex_unlock(&xprt->xprt_dbgfs_lock_lhb3); mutex_lock(&transport_list_lock_lha0); list_for_each_entry(xprt, &transport_list, list_node) diff --git a/drivers/usb/gadget/function/f_diag.c b/drivers/usb/gadget/function/f_diag.c index 7a451b77c4d0..87939140f82e 100644 --- a/drivers/usb/gadget/function/f_diag.c +++ b/drivers/usb/gadget/function/f_diag.c @@ -657,7 +657,16 @@ static void diag_function_disable(struct usb_function *f) static void diag_free_func(struct usb_function *f) { - kfree(func_to_diag(f)); + struct diag_context *ctxt = func_to_diag(f); + unsigned long flags; + + spin_lock_irqsave(&ctxt->lock, flags); + list_del(&ctxt->list_item); + if (kref_put(&ctxt->kref, diag_context_release)) + /* diag_context_release called spin_unlock already */ + local_irq_restore(flags); + else + spin_unlock_irqrestore(&ctxt->lock, flags); } static int diag_function_set_alt(struct usb_function *f, @@ -734,16 +743,11 @@ static void diag_function_unbind(struct usb_configuration *c, */ if (ctxt->ch && ctxt->ch->priv_usb == ctxt) ctxt->ch->priv_usb = NULL; - list_del(&ctxt->list_item); - /* Free any pending USB requests from last session */ + spin_lock_irqsave(&ctxt->lock, flags); + /* Free any pending USB requests from last session */ free_reqs(ctxt); - - if (kref_put(&ctxt->kref, diag_context_release)) - /* diag_context_release called spin_unlock already */ - local_irq_restore(flags); - else - spin_unlock_irqrestore(&ctxt->lock, flags); + spin_unlock_irqrestore(&ctxt->lock, flags); } static int diag_function_bind(struct usb_configuration *c, diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index 646f75653583..bb4114e90b6c 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -3748,9 +3748,9 @@ static int mdss_dsi_parse_ctrl_params(struct platform_device *ctrl_pdev, data = of_get_property(ctrl_pdev->dev.of_node, "qcom,platform-regulator-settings", &len); if (!data) { - pr_err("%s:%d, Unable to read Phy regulator settings\n", + pr_debug("%s:%d, Unable to read Phy regulator settings\n", __func__, __LINE__); - return -EINVAL; + pinfo->mipi.dsi_phy_db.regulator_len = 0; } else { pinfo->mipi.dsi_phy_db.regulator_len = len; for (i = 0; i < len; i++) diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c index b23e24362af6..619c671650ea 100644 --- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c +++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c @@ -564,6 +564,11 @@ static void mdss_dsi_28nm_phy_regulator_enable( struct mdss_dsi_phy_ctrl *pd; pd = &(((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db); + if (pd->regulator_len == 0) { + pr_warn("%s: invalid regulator settings\n", __func__); + return; + } + if (pd->reg_ldo_mode) { /* Regulator ctrl 0 */ MIPI_OUTP(ctrl_pdata->phy_regulator_io.base, 0x0); @@ -855,6 +860,12 @@ static void mdss_dsi_8996_phy_regulator_enable( void __iomem *base; pd = &(((ctrl->panel_data).panel_info.mipi).dsi_phy_db); + + if (pd->regulator_len != 5) { + pr_warn("%s: invalid regulator settings\n", __func__); + return; + } + /* 4 lanes + clk lane configuration */ for (ln = 0; ln < 5; ln++) { /* diff --git a/include/dt-bindings/clock/msm-clocks-cobalt.h b/include/dt-bindings/clock/msm-clocks-cobalt.h index 8fb7e73441bc..bd0ae1388487 100644 --- a/include/dt-bindings/clock/msm-clocks-cobalt.h +++ b/include/dt-bindings/clock/msm-clocks-cobalt.h @@ -398,8 +398,10 @@ #define clk_mmss_mdss_axi_clk 0xdf04fc1d #define clk_mmss_mdss_byte0_clk 0x38105d25 #define clk_mmss_mdss_byte0_intf_clk 0x38e5aa79 +#define clk_mmss_mdss_byte0_intf_div_clk 0x8604f181 #define clk_mmss_mdss_byte1_clk 0xe0c21354 #define clk_mmss_mdss_byte1_intf_clk 0xcf654d8e +#define clk_mmss_mdss_byte1_intf_div_clk 0xcdf334c5 #define clk_mmss_mdss_dp_aux_clk 0x23125eb6 #define clk_mmss_mdss_dp_gtc_clk 0xb59c151a #define clk_mmss_mdss_esc0_clk 0x5721ff83 diff --git a/include/dt-bindings/clock/msm-clocks-hwio-cobalt.h b/include/dt-bindings/clock/msm-clocks-hwio-cobalt.h index 22bafd3ee428..9ba814880632 100644 --- a/include/dt-bindings/clock/msm-clocks-hwio-cobalt.h +++ b/include/dt-bindings/clock/msm-clocks-hwio-cobalt.h @@ -358,8 +358,10 @@ #define MMSS_MDSS_AXI_CBCR 0x02310 #define MMSS_MDSS_BYTE0_CBCR 0x0233C #define MMSS_MDSS_BYTE0_INTF_CBCR 0x02374 +#define MMSS_MDSS_BYTE0_INTF_DIV 0x0237C #define MMSS_MDSS_BYTE1_CBCR 0x02340 #define MMSS_MDSS_BYTE1_INTF_CBCR 0x02378 +#define MMSS_MDSS_BYTE1_INTF_DIV 0x02380 #define MMSS_MDSS_DP_AUX_CBCR 0x02364 #define MMSS_MDSS_DP_CRYPTO_CBCR 0x0235C #define MMSS_MDSS_DP_GTC_CBCR 0x02368 diff --git a/include/uapi/media/msm_jpeg_dma.h b/include/uapi/media/msm_jpeg_dma.h index 44fa4ed8af52..df3c7ee5b7cf 100644 --- a/include/uapi/media/msm_jpeg_dma.h +++ b/include/uapi/media/msm_jpeg_dma.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -18,4 +18,10 @@ /* msm jpeg dma control ID's */ #define V4L2_CID_JPEG_DMA_SPEED (V4L2_CID_PRIVATE_BASE) +/* msm_jpeg_dma_buf */ +struct msm_jpeg_dma_buff { + int32_t fd; + uint32_t offset; +}; + #endif /* __UAPI_MSM_JPEG_DMA__ */ |
