Loading drivers/gpu/msm/a6xx_reg.h +1 −0 Original line number Diff line number Diff line Loading @@ -946,6 +946,7 @@ #define A6XX_GMU_CM3_SYSRESET 0x1F800 #define A6XX_GMU_CM3_BOOT_CONFIG 0x1F801 #define A6XX_GMU_CX_GMU_WFI_CONFIG 0x1F802 #define A6XX_GMU_CX_GMU_WDOG_CTRL 0x1F813 #define A6XX_GMU_CM3_FW_BUSY 0x1F81A #define A6XX_GMU_CM3_FW_INIT_RESULT 0x1F81C #define A6XX_GMU_CM3_CFG 0x1F82D Loading drivers/gpu/msm/adreno.c +25 −0 Original line number Diff line number Diff line Loading @@ -333,6 +333,28 @@ void adreno_fault_detect_stop(struct adreno_device *adreno_dev) adreno_dev->fast_hang_detect = 0; } #define GMU_CM3_CFG_NONMASKINTR_SHIFT 9 /* Send an NMI to the GMU */ void adreno_gmu_send_nmi(struct adreno_device *adreno_dev) { /* Mask so there's no interrupt caused by NMI */ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK, 0xFFFFFFFF); /* Make sure the interrupt is masked before causing it */ wmb(); if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG)) adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_NMI_CONTROL_STATUS, 0); adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_CM3_CFG, (1 << GMU_CM3_CFG_NONMASKINTR_SHIFT)); /* Make sure the NMI is invoked before we proceed*/ wmb(); } /* * A workqueue callback responsible for actually turning on the GPU after a * touch event. kgsl_pwrctrl_change_state(ACTIVE) is used without any Loading Loading @@ -1690,6 +1712,9 @@ static int adreno_init(struct kgsl_device *device) adreno_perfcounter_init(adreno_dev); adreno_fault_detect_init(adreno_dev); adreno_dev->cooperative_reset = ADRENO_FEATURE(adreno_dev, ADRENO_COOP_RESET); /* Power down the device */ if (ADRENO_GPUREV(adreno_dev) < 600) kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); Loading drivers/gpu/msm/adreno.h +4 −0 Original line number Diff line number Diff line Loading @@ -404,6 +404,8 @@ enum gpu_coresight_sources { * @ft_policy: Defines the fault tolerance policy * @long_ib_detect: Long IB detection availability * @ft_pf_policy: Defines the fault policy for page faults * @cooperative_reset: Indicates if graceful death handshake is enabled * between GMU and GPU * @profile: Container for adreno profiler information * @dispatcher: Container for adreno GPU dispatcher * @pwron_fixup: Command buffer to run a post-power collapse shader workaround Loading Loading @@ -481,6 +483,7 @@ struct adreno_device { unsigned long ft_policy; unsigned int long_ib_detect; unsigned long ft_pf_policy; bool cooperative_reset; struct adreno_profile profile; struct adreno_dispatcher dispatcher; struct kgsl_memdesc pwron_fixup; Loading Loading @@ -1812,4 +1815,5 @@ int adreno_gmu_fenced_write(struct adreno_device *adreno_dev, enum adreno_regs offset, unsigned int val, unsigned int fence_mask); int adreno_clear_pending_transactions(struct kgsl_device *device); void adreno_gmu_send_nmi(struct adreno_device *adreno_dev); #endif /*__ADRENO_H */ drivers/gpu/msm/adreno_a6xx_gmu.c +33 −0 Original line number Diff line number Diff line Loading @@ -1650,6 +1650,38 @@ static void a6xx_gmu_snapshot(struct kgsl_device *device, } } static void a6xx_gmu_cooperative_reset(struct kgsl_device *device) { struct gmu_device *gmu = KGSL_GMU_DEVICE(device); unsigned int result; gmu_core_regwrite(device, A6XX_GMU_CX_GMU_WDOG_CTRL, 0); gmu_core_regwrite(device, A6XX_GMU_HOST2GMU_INTR_SET, BIT(17)); /* * After triggering graceful death wait for snapshot ready * indication from GMU. */ if (!timed_poll_check(device, A6XX_GMU_CM3_FW_INIT_RESULT, 0x800, 2, 0x800)) return; gmu_core_regread(device, A6XX_GMU_CM3_FW_INIT_RESULT, &result); dev_err(&gmu->pdev->dev, "GMU cooperative reset timed out 0x%x\n", result); /* * If we dont get a snapshot ready from GMU, trigger NMI * and if we still timeout then we just continue with reset. */ adreno_gmu_send_nmi(ADRENO_DEVICE(device)); udelay(200); gmu_core_regread(device, A6XX_GMU_CM3_FW_INIT_RESULT, &result); if ((result & 0x800) != 0x800) dev_err(&gmu->pdev->dev, "GMU cooperative reset NMI timed out 0x%x\n", result); } static int a6xx_gmu_wait_for_active_transition( struct kgsl_device *device) { Loading Loading @@ -1692,6 +1724,7 @@ struct gmu_dev_ops adreno_a6xx_gmudev = { .ifpc_store = a6xx_gmu_ifpc_store, .ifpc_show = a6xx_gmu_ifpc_show, .snapshot = a6xx_gmu_snapshot, .cooperative_reset = a6xx_gmu_cooperative_reset, .wait_for_active_transition = a6xx_gmu_wait_for_active_transition, .gmu2host_intr_mask = HFI_IRQ_MASK, .gmu_ao_intr_mask = GMU_AO_INT_MASK, Loading drivers/gpu/msm/adreno_debugfs.c +28 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ #include <linux/msm_kgsl.h> #include "adreno.h" extern struct dentry *kgsl_debugfs_dir; static int _isdb_set(void *data, u64 val) { Loading Loading @@ -110,6 +111,27 @@ static int _active_count_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(_active_count_fops, _active_count_get, NULL, "%llu\n"); static int _coop_reset_set(void *data, u64 val) { struct kgsl_device *device = data; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); if (ADRENO_FEATURE(adreno_dev, ADRENO_COOP_RESET)) adreno_dev->cooperative_reset = val ? true : false; return 0; } static int _coop_reset_get(void *data, u64 *val) { struct kgsl_device *device = data; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); *val = (u64) adreno_dev->cooperative_reset; return 0; } DEFINE_DEBUGFS_ATTRIBUTE(_coop_reset_fops, _coop_reset_get, _coop_reset_set, "%llu\n"); typedef void (*reg_read_init_t)(struct kgsl_device *device); typedef void (*reg_read_fill_t)(struct kgsl_device *device, int i, unsigned int *vals, int linec); Loading Loading @@ -362,6 +384,7 @@ adreno_context_debugfs_init(struct adreno_device *adreno_dev, void adreno_debugfs_init(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct dentry *snapshot_dir; if (IS_ERR_OR_NULL(device->d_debugfs)) return; Loading @@ -370,6 +393,11 @@ void adreno_debugfs_init(struct adreno_device *adreno_dev) &_active_count_fops); adreno_dev->ctx_d_debugfs = debugfs_create_dir("ctx", device->d_debugfs); snapshot_dir = debugfs_lookup("snapshot", kgsl_debugfs_dir); if (!IS_ERR_OR_NULL(snapshot_dir)) debugfs_create_file("coop_reset", 0644, snapshot_dir, device, &_coop_reset_fops); if (ADRENO_FEATURE(adreno_dev, ADRENO_LM)) { debugfs_create_file("lm_limit", 0644, device->d_debugfs, device, Loading Loading
drivers/gpu/msm/a6xx_reg.h +1 −0 Original line number Diff line number Diff line Loading @@ -946,6 +946,7 @@ #define A6XX_GMU_CM3_SYSRESET 0x1F800 #define A6XX_GMU_CM3_BOOT_CONFIG 0x1F801 #define A6XX_GMU_CX_GMU_WFI_CONFIG 0x1F802 #define A6XX_GMU_CX_GMU_WDOG_CTRL 0x1F813 #define A6XX_GMU_CM3_FW_BUSY 0x1F81A #define A6XX_GMU_CM3_FW_INIT_RESULT 0x1F81C #define A6XX_GMU_CM3_CFG 0x1F82D Loading
drivers/gpu/msm/adreno.c +25 −0 Original line number Diff line number Diff line Loading @@ -333,6 +333,28 @@ void adreno_fault_detect_stop(struct adreno_device *adreno_dev) adreno_dev->fast_hang_detect = 0; } #define GMU_CM3_CFG_NONMASKINTR_SHIFT 9 /* Send an NMI to the GMU */ void adreno_gmu_send_nmi(struct adreno_device *adreno_dev) { /* Mask so there's no interrupt caused by NMI */ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK, 0xFFFFFFFF); /* Make sure the interrupt is masked before causing it */ wmb(); if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG)) adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_NMI_CONTROL_STATUS, 0); adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_CM3_CFG, (1 << GMU_CM3_CFG_NONMASKINTR_SHIFT)); /* Make sure the NMI is invoked before we proceed*/ wmb(); } /* * A workqueue callback responsible for actually turning on the GPU after a * touch event. kgsl_pwrctrl_change_state(ACTIVE) is used without any Loading Loading @@ -1690,6 +1712,9 @@ static int adreno_init(struct kgsl_device *device) adreno_perfcounter_init(adreno_dev); adreno_fault_detect_init(adreno_dev); adreno_dev->cooperative_reset = ADRENO_FEATURE(adreno_dev, ADRENO_COOP_RESET); /* Power down the device */ if (ADRENO_GPUREV(adreno_dev) < 600) kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); Loading
drivers/gpu/msm/adreno.h +4 −0 Original line number Diff line number Diff line Loading @@ -404,6 +404,8 @@ enum gpu_coresight_sources { * @ft_policy: Defines the fault tolerance policy * @long_ib_detect: Long IB detection availability * @ft_pf_policy: Defines the fault policy for page faults * @cooperative_reset: Indicates if graceful death handshake is enabled * between GMU and GPU * @profile: Container for adreno profiler information * @dispatcher: Container for adreno GPU dispatcher * @pwron_fixup: Command buffer to run a post-power collapse shader workaround Loading Loading @@ -481,6 +483,7 @@ struct adreno_device { unsigned long ft_policy; unsigned int long_ib_detect; unsigned long ft_pf_policy; bool cooperative_reset; struct adreno_profile profile; struct adreno_dispatcher dispatcher; struct kgsl_memdesc pwron_fixup; Loading Loading @@ -1812,4 +1815,5 @@ int adreno_gmu_fenced_write(struct adreno_device *adreno_dev, enum adreno_regs offset, unsigned int val, unsigned int fence_mask); int adreno_clear_pending_transactions(struct kgsl_device *device); void adreno_gmu_send_nmi(struct adreno_device *adreno_dev); #endif /*__ADRENO_H */
drivers/gpu/msm/adreno_a6xx_gmu.c +33 −0 Original line number Diff line number Diff line Loading @@ -1650,6 +1650,38 @@ static void a6xx_gmu_snapshot(struct kgsl_device *device, } } static void a6xx_gmu_cooperative_reset(struct kgsl_device *device) { struct gmu_device *gmu = KGSL_GMU_DEVICE(device); unsigned int result; gmu_core_regwrite(device, A6XX_GMU_CX_GMU_WDOG_CTRL, 0); gmu_core_regwrite(device, A6XX_GMU_HOST2GMU_INTR_SET, BIT(17)); /* * After triggering graceful death wait for snapshot ready * indication from GMU. */ if (!timed_poll_check(device, A6XX_GMU_CM3_FW_INIT_RESULT, 0x800, 2, 0x800)) return; gmu_core_regread(device, A6XX_GMU_CM3_FW_INIT_RESULT, &result); dev_err(&gmu->pdev->dev, "GMU cooperative reset timed out 0x%x\n", result); /* * If we dont get a snapshot ready from GMU, trigger NMI * and if we still timeout then we just continue with reset. */ adreno_gmu_send_nmi(ADRENO_DEVICE(device)); udelay(200); gmu_core_regread(device, A6XX_GMU_CM3_FW_INIT_RESULT, &result); if ((result & 0x800) != 0x800) dev_err(&gmu->pdev->dev, "GMU cooperative reset NMI timed out 0x%x\n", result); } static int a6xx_gmu_wait_for_active_transition( struct kgsl_device *device) { Loading Loading @@ -1692,6 +1724,7 @@ struct gmu_dev_ops adreno_a6xx_gmudev = { .ifpc_store = a6xx_gmu_ifpc_store, .ifpc_show = a6xx_gmu_ifpc_show, .snapshot = a6xx_gmu_snapshot, .cooperative_reset = a6xx_gmu_cooperative_reset, .wait_for_active_transition = a6xx_gmu_wait_for_active_transition, .gmu2host_intr_mask = HFI_IRQ_MASK, .gmu_ao_intr_mask = GMU_AO_INT_MASK, Loading
drivers/gpu/msm/adreno_debugfs.c +28 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ #include <linux/msm_kgsl.h> #include "adreno.h" extern struct dentry *kgsl_debugfs_dir; static int _isdb_set(void *data, u64 val) { Loading Loading @@ -110,6 +111,27 @@ static int _active_count_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(_active_count_fops, _active_count_get, NULL, "%llu\n"); static int _coop_reset_set(void *data, u64 val) { struct kgsl_device *device = data; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); if (ADRENO_FEATURE(adreno_dev, ADRENO_COOP_RESET)) adreno_dev->cooperative_reset = val ? true : false; return 0; } static int _coop_reset_get(void *data, u64 *val) { struct kgsl_device *device = data; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); *val = (u64) adreno_dev->cooperative_reset; return 0; } DEFINE_DEBUGFS_ATTRIBUTE(_coop_reset_fops, _coop_reset_get, _coop_reset_set, "%llu\n"); typedef void (*reg_read_init_t)(struct kgsl_device *device); typedef void (*reg_read_fill_t)(struct kgsl_device *device, int i, unsigned int *vals, int linec); Loading Loading @@ -362,6 +384,7 @@ adreno_context_debugfs_init(struct adreno_device *adreno_dev, void adreno_debugfs_init(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct dentry *snapshot_dir; if (IS_ERR_OR_NULL(device->d_debugfs)) return; Loading @@ -370,6 +393,11 @@ void adreno_debugfs_init(struct adreno_device *adreno_dev) &_active_count_fops); adreno_dev->ctx_d_debugfs = debugfs_create_dir("ctx", device->d_debugfs); snapshot_dir = debugfs_lookup("snapshot", kgsl_debugfs_dir); if (!IS_ERR_OR_NULL(snapshot_dir)) debugfs_create_file("coop_reset", 0644, snapshot_dir, device, &_coop_reset_fops); if (ADRENO_FEATURE(adreno_dev, ADRENO_LM)) { debugfs_create_file("lm_limit", 0644, device->d_debugfs, device, Loading