| .. | .. |
|---|
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note |
|---|
| 2 | 2 | /* |
|---|
| 3 | 3 | * |
|---|
| 4 | | - * (C) COPYRIGHT 2010-2021 ARM Limited. All rights reserved. |
|---|
| 4 | + * (C) COPYRIGHT 2010-2022 ARM Limited. All rights reserved. |
|---|
| 5 | 5 | * |
|---|
| 6 | 6 | * This program is free software and is provided to you under the terms of the |
|---|
| 7 | 7 | * GNU General Public License version 2 as published by the Free Software |
|---|
| .. | .. |
|---|
| 39 | 39 | |
|---|
| 40 | 40 | #include <mali_kbase_reset_gpu.h> |
|---|
| 41 | 41 | #include <mali_kbase_ctx_sched.h> |
|---|
| 42 | | -#include <mali_kbase_hwcnt_context.h> |
|---|
| 42 | +#include <hwcnt/mali_kbase_hwcnt_context.h> |
|---|
| 43 | +#include <mali_kbase_pbha.h> |
|---|
| 43 | 44 | #include <backend/gpu/mali_kbase_cache_policy_backend.h> |
|---|
| 44 | 45 | #include <device/mali_kbase_device.h> |
|---|
| 45 | 46 | #include <backend/gpu/mali_kbase_irq_internal.h> |
|---|
| .. | .. |
|---|
| 51 | 52 | #endif /* CONFIG_MALI_ARBITER_SUPPORT */ |
|---|
| 52 | 53 | #if MALI_USE_CSF |
|---|
| 53 | 54 | #include <csf/ipa_control/mali_kbase_csf_ipa_control.h> |
|---|
| 55 | +#endif |
|---|
| 56 | + |
|---|
| 57 | +#if MALI_USE_CSF |
|---|
| 58 | +#include <linux/delay.h> |
|---|
| 54 | 59 | #endif |
|---|
| 55 | 60 | |
|---|
| 56 | 61 | #include <linux/of.h> |
|---|
| .. | .. |
|---|
| 71 | 76 | /** |
|---|
| 72 | 77 | * enum kbasep_pm_action - Actions that can be performed on a core. |
|---|
| 73 | 78 | * |
|---|
| 74 | | - * This enumeration is private to the file. Its values are set to allow |
|---|
| 75 | | - * core_type_to_reg() function, which decodes this enumeration, to be simpler |
|---|
| 76 | | - * and more efficient. |
|---|
| 77 | | - * |
|---|
| 78 | 79 | * @ACTION_PRESENT: The cores that are present |
|---|
| 79 | 80 | * @ACTION_READY: The cores that are ready |
|---|
| 80 | 81 | * @ACTION_PWRON: Power on the cores specified |
|---|
| 81 | 82 | * @ACTION_PWROFF: Power off the cores specified |
|---|
| 82 | 83 | * @ACTION_PWRTRANS: The cores that are transitioning |
|---|
| 83 | 84 | * @ACTION_PWRACTIVE: The cores that are active |
|---|
| 85 | + * |
|---|
| 86 | + * This enumeration is private to the file. Its values are set to allow |
|---|
| 87 | + * core_type_to_reg() function, which decodes this enumeration, to be simpler |
|---|
| 88 | + * and more efficient. |
|---|
| 84 | 89 | */ |
|---|
| 85 | 90 | enum kbasep_pm_action { |
|---|
| 86 | 91 | ACTION_PRESENT = 0, |
|---|
| .. | .. |
|---|
| 96 | 101 | enum kbase_pm_core_type core_type, |
|---|
| 97 | 102 | enum kbasep_pm_action action); |
|---|
| 98 | 103 | |
|---|
| 104 | +static void kbase_pm_hw_issues_apply(struct kbase_device *kbdev); |
|---|
| 105 | + |
|---|
| 99 | 106 | #if MALI_USE_CSF |
|---|
| 100 | 107 | bool kbase_pm_is_mcu_desired(struct kbase_device *kbdev) |
|---|
| 101 | 108 | { |
|---|
| .. | .. |
|---|
| 104 | 111 | if (unlikely(!kbdev->csf.firmware_inited)) |
|---|
| 105 | 112 | return false; |
|---|
| 106 | 113 | |
|---|
| 107 | | - if (kbdev->csf.scheduler.pm_active_count) |
|---|
| 114 | + if (kbdev->csf.scheduler.pm_active_count && |
|---|
| 115 | + kbdev->pm.backend.mcu_desired) |
|---|
| 108 | 116 | return true; |
|---|
| 117 | + |
|---|
| 118 | +#ifdef KBASE_PM_RUNTIME |
|---|
| 119 | + if (kbdev->pm.backend.gpu_wakeup_override) |
|---|
| 120 | + return true; |
|---|
| 121 | +#endif |
|---|
| 109 | 122 | |
|---|
| 110 | 123 | /* MCU is supposed to be ON, only when scheduler.pm_active_count is |
|---|
| 111 | 124 | * non zero. But for always_on policy, the MCU needs to be kept on, |
|---|
| .. | .. |
|---|
| 120 | 133 | |
|---|
| 121 | 134 | bool kbase_pm_is_l2_desired(struct kbase_device *kbdev) |
|---|
| 122 | 135 | { |
|---|
| 136 | +#if !MALI_USE_CSF |
|---|
| 123 | 137 | if (kbdev->pm.backend.protected_entry_transition_override) |
|---|
| 124 | 138 | return false; |
|---|
| 125 | 139 | |
|---|
| .. | .. |
|---|
| 130 | 144 | if (kbdev->pm.backend.protected_transition_override && |
|---|
| 131 | 145 | !kbdev->pm.backend.shaders_desired) |
|---|
| 132 | 146 | return false; |
|---|
| 133 | | - |
|---|
| 134 | | -#if MALI_USE_CSF |
|---|
| 135 | | - if (kbdev->pm.backend.policy_change_clamp_state_to_off) |
|---|
| 147 | +#else |
|---|
| 148 | + if (unlikely(kbdev->pm.backend.policy_change_clamp_state_to_off)) |
|---|
| 136 | 149 | return false; |
|---|
| 150 | + |
|---|
| 151 | + /* Power up the L2 cache only when MCU is desired */ |
|---|
| 152 | + if (likely(kbdev->csf.firmware_inited)) |
|---|
| 153 | + return kbase_pm_is_mcu_desired(kbdev); |
|---|
| 137 | 154 | #endif |
|---|
| 138 | 155 | |
|---|
| 139 | 156 | return kbdev->pm.backend.l2_desired; |
|---|
| 140 | 157 | } |
|---|
| 141 | 158 | |
|---|
| 159 | +#if !MALI_USE_CSF |
|---|
| 142 | 160 | void kbase_pm_protected_override_enable(struct kbase_device *kbdev) |
|---|
| 143 | 161 | { |
|---|
| 144 | 162 | lockdep_assert_held(&kbdev->hwaccess_lock); |
|---|
| .. | .. |
|---|
| 204 | 222 | |
|---|
| 205 | 223 | kbase_pm_update_state(kbdev); |
|---|
| 206 | 224 | } |
|---|
| 225 | +#endif |
|---|
| 207 | 226 | |
|---|
| 208 | 227 | /** |
|---|
| 209 | 228 | * core_type_to_reg - Decode a core type and action to a register. |
|---|
| 229 | + * |
|---|
| 230 | + * @core_type: The type of core |
|---|
| 231 | + * @action: The type of action |
|---|
| 210 | 232 | * |
|---|
| 211 | 233 | * Given a core type (defined by kbase_pm_core_type) and an action (defined |
|---|
| 212 | 234 | * by kbasep_pm_action) this function will return the register offset that |
|---|
| 213 | 235 | * will perform the action on the core type. The register returned is the _LO |
|---|
| 214 | 236 | * register and an offset must be applied to use the _HI register. |
|---|
| 215 | | - * |
|---|
| 216 | | - * @core_type: The type of core |
|---|
| 217 | | - * @action: The type of action |
|---|
| 218 | 237 | * |
|---|
| 219 | 238 | * Return: The register offset of the _LO register that performs an action of |
|---|
| 220 | 239 | * type @action on a core of type @core_type. |
|---|
| .. | .. |
|---|
| 259 | 278 | * to be called from. |
|---|
| 260 | 279 | */ |
|---|
| 261 | 280 | |
|---|
| 262 | | - kbase_reg_write(kbdev, |
|---|
| 263 | | - GPU_CONTROL_REG(GPU_COMMAND), |
|---|
| 264 | | - GPU_COMMAND_CLEAN_INV_CACHES); |
|---|
| 281 | + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), |
|---|
| 282 | + GPU_COMMAND_CACHE_CLN_INV_L2); |
|---|
| 265 | 283 | |
|---|
| 266 | 284 | raw = kbase_reg_read(kbdev, |
|---|
| 267 | 285 | GPU_CONTROL_REG(GPU_IRQ_RAWSTAT)); |
|---|
| .. | .. |
|---|
| 279 | 297 | /** |
|---|
| 280 | 298 | * kbase_pm_invoke - Invokes an action on a core set |
|---|
| 281 | 299 | * |
|---|
| 282 | | - * This function performs the action given by @action on a set of cores of a |
|---|
| 283 | | - * type given by @core_type. It is a static function used by |
|---|
| 284 | | - * kbase_pm_transition_core_type() |
|---|
| 285 | | - * |
|---|
| 286 | 300 | * @kbdev: The kbase device structure of the device |
|---|
| 287 | 301 | * @core_type: The type of core that the action should be performed on |
|---|
| 288 | 302 | * @cores: A bit mask of cores to perform the action on (low 32 bits) |
|---|
| 289 | 303 | * @action: The action to perform on the cores |
|---|
| 304 | + * |
|---|
| 305 | + * This function performs the action given by @action on a set of cores of a |
|---|
| 306 | + * type given by @core_type. It is a static function used by |
|---|
| 307 | + * kbase_pm_transition_core_type() |
|---|
| 290 | 308 | */ |
|---|
| 291 | 309 | static void kbase_pm_invoke(struct kbase_device *kbdev, |
|---|
| 292 | 310 | enum kbase_pm_core_type core_type, |
|---|
| .. | .. |
|---|
| 364 | 382 | /** |
|---|
| 365 | 383 | * kbase_pm_get_state - Get information about a core set |
|---|
| 366 | 384 | * |
|---|
| 385 | + * @kbdev: The kbase device structure of the device |
|---|
| 386 | + * @core_type: The type of core that the should be queried |
|---|
| 387 | + * @action: The property of the cores to query |
|---|
| 388 | + * |
|---|
| 367 | 389 | * This function gets information (chosen by @action) about a set of cores of |
|---|
| 368 | 390 | * a type given by @core_type. It is a static function used by |
|---|
| 369 | 391 | * kbase_pm_get_active_cores(), kbase_pm_get_trans_cores() and |
|---|
| 370 | 392 | * kbase_pm_get_ready_cores(). |
|---|
| 371 | | - * |
|---|
| 372 | | - * @kbdev: The kbase device structure of the device |
|---|
| 373 | | - * @core_type: The type of core that the should be queried |
|---|
| 374 | | - * @action: The property of the cores to query |
|---|
| 375 | 393 | * |
|---|
| 376 | 394 | * Return: A bit mask specifying the state of the cores |
|---|
| 377 | 395 | */ |
|---|
| .. | .. |
|---|
| 520 | 538 | if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_L2_CONFIG)) |
|---|
| 521 | 539 | return; |
|---|
| 522 | 540 | |
|---|
| 541 | +#if MALI_USE_CSF |
|---|
| 542 | + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PBHA_HWU)) { |
|---|
| 543 | + val = kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_CONFIG)); |
|---|
| 544 | + kbase_reg_write(kbdev, GPU_CONTROL_REG(L2_CONFIG), |
|---|
| 545 | + L2_CONFIG_PBHA_HWU_SET(val, kbdev->pbha_propagate_bits)); |
|---|
| 546 | + } |
|---|
| 547 | +#endif /* MALI_USE_CSF */ |
|---|
| 548 | + |
|---|
| 523 | 549 | /* |
|---|
| 524 | 550 | * Skip if size and hash are not given explicitly, |
|---|
| 525 | 551 | * which means default values are used. |
|---|
| .. | .. |
|---|
| 581 | 607 | return strings[state]; |
|---|
| 582 | 608 | } |
|---|
| 583 | 609 | |
|---|
| 610 | +static |
|---|
| 611 | +void kbase_ktrace_log_mcu_state(struct kbase_device *kbdev, enum kbase_mcu_state state) |
|---|
| 612 | +{ |
|---|
| 613 | +#if KBASE_KTRACE_ENABLE |
|---|
| 614 | + switch (state) { |
|---|
| 615 | +#define KBASEP_MCU_STATE(n) \ |
|---|
| 616 | + case KBASE_MCU_ ## n: \ |
|---|
| 617 | + KBASE_KTRACE_ADD(kbdev, PM_MCU_ ## n, NULL, state); \ |
|---|
| 618 | + break; |
|---|
| 619 | +#include "mali_kbase_pm_mcu_states.h" |
|---|
| 620 | +#undef KBASEP_MCU_STATE |
|---|
| 621 | + } |
|---|
| 622 | +#endif |
|---|
| 623 | +} |
|---|
| 624 | + |
|---|
| 584 | 625 | static inline bool kbase_pm_handle_mcu_core_attr_update(struct kbase_device *kbdev) |
|---|
| 585 | 626 | { |
|---|
| 586 | 627 | struct kbase_pm_backend_data *backend = &kbdev->pm.backend; |
|---|
| .. | .. |
|---|
| 610 | 651 | return (core_mask_update || timer_update); |
|---|
| 611 | 652 | } |
|---|
| 612 | 653 | |
|---|
| 654 | +bool kbase_pm_is_mcu_inactive(struct kbase_device *kbdev, |
|---|
| 655 | + enum kbase_mcu_state state) |
|---|
| 656 | +{ |
|---|
| 657 | + lockdep_assert_held(&kbdev->hwaccess_lock); |
|---|
| 658 | + |
|---|
| 659 | + return ((state == KBASE_MCU_OFF) || (state == KBASE_MCU_IN_SLEEP)); |
|---|
| 660 | +} |
|---|
| 661 | + |
|---|
| 662 | +#ifdef KBASE_PM_RUNTIME |
|---|
| 663 | +/** |
|---|
| 664 | + * kbase_pm_enable_mcu_db_notification - Enable the Doorbell notification on |
|---|
| 665 | + * MCU side |
|---|
| 666 | + * |
|---|
| 667 | + * @kbdev: Pointer to the device. |
|---|
| 668 | + * |
|---|
| 669 | + * This function is called to re-enable the Doorbell notification on MCU side |
|---|
| 670 | + * when MCU needs to beome active again. |
|---|
| 671 | + */ |
|---|
| 672 | +static void kbase_pm_enable_mcu_db_notification(struct kbase_device *kbdev) |
|---|
| 673 | +{ |
|---|
| 674 | + u32 val = kbase_reg_read(kbdev, GPU_CONTROL_REG(MCU_CONTROL)); |
|---|
| 675 | + |
|---|
| 676 | + lockdep_assert_held(&kbdev->hwaccess_lock); |
|---|
| 677 | + |
|---|
| 678 | + val &= ~MCU_CNTRL_DOORBELL_DISABLE_MASK; |
|---|
| 679 | + kbase_reg_write(kbdev, GPU_CONTROL_REG(MCU_CONTROL), val); |
|---|
| 680 | +} |
|---|
| 681 | + |
|---|
| 682 | +/** |
|---|
| 683 | + * wait_mcu_as_inactive - Wait for AS used by MCU FW to get configured |
|---|
| 684 | + * |
|---|
| 685 | + * @kbdev: Pointer to the device. |
|---|
| 686 | + * |
|---|
| 687 | + * This function is called to wait for the AS used by MCU FW to get configured |
|---|
| 688 | + * before DB notification on MCU is enabled, as a workaround for HW issue. |
|---|
| 689 | + */ |
|---|
| 690 | +static void wait_mcu_as_inactive(struct kbase_device *kbdev) |
|---|
| 691 | +{ |
|---|
| 692 | + unsigned int max_loops = KBASE_AS_INACTIVE_MAX_LOOPS; |
|---|
| 693 | + |
|---|
| 694 | + lockdep_assert_held(&kbdev->hwaccess_lock); |
|---|
| 695 | + |
|---|
| 696 | + if (!kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TURSEHW_2716)) |
|---|
| 697 | + return; |
|---|
| 698 | + |
|---|
| 699 | + /* Wait for the AS_ACTIVE_INT bit to become 0 for the AS used by MCU FW */ |
|---|
| 700 | + while (--max_loops && |
|---|
| 701 | + kbase_reg_read(kbdev, MMU_AS_REG(MCU_AS_NR, AS_STATUS)) & |
|---|
| 702 | + AS_STATUS_AS_ACTIVE_INT) |
|---|
| 703 | + ; |
|---|
| 704 | + |
|---|
| 705 | + if (!WARN_ON_ONCE(max_loops == 0)) |
|---|
| 706 | + return; |
|---|
| 707 | + |
|---|
| 708 | + dev_err(kbdev->dev, "AS_ACTIVE_INT bit stuck for AS %d used by MCU FW", MCU_AS_NR); |
|---|
| 709 | + |
|---|
| 710 | + if (kbase_prepare_to_reset_gpu(kbdev, 0)) |
|---|
| 711 | + kbase_reset_gpu(kbdev); |
|---|
| 712 | +} |
|---|
| 713 | +#endif |
|---|
| 714 | + |
|---|
| 715 | +/** |
|---|
| 716 | + * kbasep_pm_toggle_power_interrupt - Toggles the IRQ mask for power interrupts |
|---|
| 717 | + * from the firmware |
|---|
| 718 | + * |
|---|
| 719 | + * @kbdev: Pointer to the device |
|---|
| 720 | + * @enable: boolean indicating to enable interrupts or not |
|---|
| 721 | + * |
|---|
| 722 | + * The POWER_CHANGED_ALL interrupt can be disabled after L2 has been turned on |
|---|
| 723 | + * when FW is controlling the power for the shader cores. Correspondingly, the |
|---|
| 724 | + * interrupts can be re-enabled after the MCU has been disabled before the |
|---|
| 725 | + * power down of L2. |
|---|
| 726 | + */ |
|---|
| 727 | +static void kbasep_pm_toggle_power_interrupt(struct kbase_device *kbdev, bool enable) |
|---|
| 728 | +{ |
|---|
| 729 | + u32 irq_mask; |
|---|
| 730 | + |
|---|
| 731 | + lockdep_assert_held(&kbdev->hwaccess_lock); |
|---|
| 732 | + |
|---|
| 733 | + irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK)); |
|---|
| 734 | + |
|---|
| 735 | + if (enable) { |
|---|
| 736 | + irq_mask |= POWER_CHANGED_ALL; |
|---|
| 737 | + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), POWER_CHANGED_ALL); |
|---|
| 738 | + } else { |
|---|
| 739 | + irq_mask &= ~POWER_CHANGED_ALL; |
|---|
| 740 | + } |
|---|
| 741 | + |
|---|
| 742 | + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), irq_mask); |
|---|
| 743 | +} |
|---|
| 744 | + |
|---|
| 613 | 745 | static int kbase_pm_mcu_update_state(struct kbase_device *kbdev) |
|---|
| 614 | 746 | { |
|---|
| 615 | 747 | struct kbase_pm_backend_data *backend = &kbdev->pm.backend; |
|---|
| .. | .. |
|---|
| 618 | 750 | lockdep_assert_held(&kbdev->hwaccess_lock); |
|---|
| 619 | 751 | |
|---|
| 620 | 752 | /* |
|---|
| 621 | | - * Initial load of firmare should have been done to |
|---|
| 753 | + * Initial load of firmware should have been done to |
|---|
| 622 | 754 | * exercise the MCU state machine. |
|---|
| 623 | 755 | */ |
|---|
| 624 | 756 | if (unlikely(!kbdev->csf.firmware_inited)) { |
|---|
| 625 | 757 | WARN_ON(backend->mcu_state != KBASE_MCU_OFF); |
|---|
| 626 | | - return -EIO; |
|---|
| 758 | + return 0; |
|---|
| 627 | 759 | } |
|---|
| 628 | 760 | |
|---|
| 629 | 761 | do { |
|---|
| .. | .. |
|---|
| 653 | 785 | kbase_pm_ca_get_core_mask(kbdev); |
|---|
| 654 | 786 | kbase_csf_firmware_global_reinit(kbdev, |
|---|
| 655 | 787 | backend->shaders_desired_mask); |
|---|
| 788 | + if (!kbdev->csf.firmware_hctl_core_pwr) |
|---|
| 789 | + kbasep_pm_toggle_power_interrupt(kbdev, false); |
|---|
| 656 | 790 | backend->mcu_state = |
|---|
| 657 | 791 | KBASE_MCU_ON_GLB_REINIT_PEND; |
|---|
| 658 | 792 | } |
|---|
| .. | .. |
|---|
| 670 | 804 | KBASE_MCU_HCTL_SHADERS_PEND_ON; |
|---|
| 671 | 805 | } else |
|---|
| 672 | 806 | backend->mcu_state = KBASE_MCU_ON_HWCNT_ENABLE; |
|---|
| 807 | +#if IS_ENABLED(CONFIG_MALI_CORESIGHT) |
|---|
| 808 | + if (kbase_debug_coresight_csf_state_check( |
|---|
| 809 | + kbdev, KBASE_DEBUG_CORESIGHT_CSF_DISABLED)) { |
|---|
| 810 | + kbase_debug_coresight_csf_state_request( |
|---|
| 811 | + kbdev, KBASE_DEBUG_CORESIGHT_CSF_ENABLED); |
|---|
| 812 | + backend->mcu_state = KBASE_MCU_CORESIGHT_ENABLE; |
|---|
| 813 | + } else if (kbase_debug_coresight_csf_state_check( |
|---|
| 814 | + kbdev, KBASE_DEBUG_CORESIGHT_CSF_ENABLED)) { |
|---|
| 815 | + backend->mcu_state = KBASE_MCU_CORESIGHT_ENABLE; |
|---|
| 816 | + } |
|---|
| 817 | +#endif /* IS_ENABLED(CONFIG_MALI_CORESIGHT) */ |
|---|
| 673 | 818 | } |
|---|
| 674 | 819 | break; |
|---|
| 675 | 820 | |
|---|
| .. | .. |
|---|
| 698 | 843 | unsigned long flags; |
|---|
| 699 | 844 | |
|---|
| 700 | 845 | kbase_csf_scheduler_spin_lock(kbdev, &flags); |
|---|
| 701 | | - kbase_hwcnt_context_enable( |
|---|
| 702 | | - kbdev->hwcnt_gpu_ctx); |
|---|
| 846 | + kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); |
|---|
| 703 | 847 | kbase_csf_scheduler_spin_unlock(kbdev, flags); |
|---|
| 704 | 848 | backend->hwcnt_disabled = false; |
|---|
| 705 | 849 | } |
|---|
| .. | .. |
|---|
| 712 | 856 | if (!kbase_pm_is_mcu_desired(kbdev)) |
|---|
| 713 | 857 | backend->mcu_state = KBASE_MCU_ON_HWCNT_DISABLE; |
|---|
| 714 | 858 | else if (kbdev->csf.firmware_hctl_core_pwr) { |
|---|
| 715 | | - /* Host control add additional Cores to be active */ |
|---|
| 716 | | - if (backend->shaders_desired_mask & ~shaders_ready) { |
|---|
| 859 | + /* Host control scale up/down cores as needed */ |
|---|
| 860 | + if (backend->shaders_desired_mask != shaders_ready) { |
|---|
| 717 | 861 | backend->hwcnt_desired = false; |
|---|
| 718 | 862 | if (!backend->hwcnt_disabled) |
|---|
| 719 | 863 | kbase_pm_trigger_hwcnt_disable(kbdev); |
|---|
| .. | .. |
|---|
| 721 | 865 | KBASE_MCU_HCTL_MCU_ON_RECHECK; |
|---|
| 722 | 866 | } |
|---|
| 723 | 867 | } else if (kbase_pm_handle_mcu_core_attr_update(kbdev)) |
|---|
| 724 | | - kbdev->pm.backend.mcu_state = |
|---|
| 725 | | - KBASE_MCU_ON_CORE_ATTR_UPDATE_PEND; |
|---|
| 868 | + backend->mcu_state = KBASE_MCU_ON_CORE_ATTR_UPDATE_PEND; |
|---|
| 869 | +#if IS_ENABLED(CONFIG_MALI_CORESIGHT) |
|---|
| 870 | + else if (kbdev->csf.coresight.disable_on_pmode_enter) { |
|---|
| 871 | + kbase_debug_coresight_csf_state_request( |
|---|
| 872 | + kbdev, KBASE_DEBUG_CORESIGHT_CSF_DISABLED); |
|---|
| 873 | + backend->mcu_state = KBASE_MCU_ON_PMODE_ENTER_CORESIGHT_DISABLE; |
|---|
| 874 | + } else if (kbdev->csf.coresight.enable_on_pmode_exit) { |
|---|
| 875 | + kbase_debug_coresight_csf_state_request( |
|---|
| 876 | + kbdev, KBASE_DEBUG_CORESIGHT_CSF_ENABLED); |
|---|
| 877 | + backend->mcu_state = KBASE_MCU_ON_PMODE_EXIT_CORESIGHT_ENABLE; |
|---|
| 878 | + } |
|---|
| 879 | +#endif |
|---|
| 726 | 880 | break; |
|---|
| 727 | 881 | |
|---|
| 728 | 882 | case KBASE_MCU_HCTL_MCU_ON_RECHECK: |
|---|
| .. | .. |
|---|
| 746 | 900 | ACTION_PWRON); |
|---|
| 747 | 901 | backend->mcu_state = |
|---|
| 748 | 902 | KBASE_MCU_HCTL_SHADERS_PEND_ON; |
|---|
| 903 | + |
|---|
| 904 | + } else if (~backend->shaders_desired_mask & shaders_ready) { |
|---|
| 905 | + kbase_csf_firmware_update_core_attr(kbdev, false, true, |
|---|
| 906 | + backend->shaders_desired_mask); |
|---|
| 907 | + backend->mcu_state = KBASE_MCU_HCTL_CORES_DOWN_SCALE_NOTIFY_PEND; |
|---|
| 749 | 908 | } else { |
|---|
| 750 | 909 | backend->mcu_state = |
|---|
| 751 | 910 | KBASE_MCU_HCTL_SHADERS_PEND_ON; |
|---|
| 752 | 911 | } |
|---|
| 753 | 912 | break; |
|---|
| 754 | 913 | |
|---|
| 914 | + case KBASE_MCU_HCTL_CORES_DOWN_SCALE_NOTIFY_PEND: |
|---|
| 915 | + if (kbase_csf_firmware_core_attr_updated(kbdev)) { |
|---|
| 916 | + /* wait in queue until cores idle */ |
|---|
| 917 | + queue_work(backend->core_idle_wq, &backend->core_idle_work); |
|---|
| 918 | + backend->mcu_state = KBASE_MCU_HCTL_CORE_INACTIVE_PEND; |
|---|
| 919 | + } |
|---|
| 920 | + break; |
|---|
| 921 | + |
|---|
| 922 | + case KBASE_MCU_HCTL_CORE_INACTIVE_PEND: |
|---|
| 923 | + { |
|---|
| 924 | + u64 active_cores = kbase_pm_get_active_cores( |
|---|
| 925 | + kbdev, |
|---|
| 926 | + KBASE_PM_CORE_SHADER); |
|---|
| 927 | + u64 cores_to_disable = shaders_ready & |
|---|
| 928 | + ~backend->shaders_desired_mask; |
|---|
| 929 | + |
|---|
| 930 | + if (!(cores_to_disable & active_cores)) { |
|---|
| 931 | + kbase_pm_invoke(kbdev, KBASE_PM_CORE_SHADER, |
|---|
| 932 | + cores_to_disable, |
|---|
| 933 | + ACTION_PWROFF); |
|---|
| 934 | + backend->shaders_avail = backend->shaders_desired_mask; |
|---|
| 935 | + backend->mcu_state = KBASE_MCU_HCTL_SHADERS_CORE_OFF_PEND; |
|---|
| 936 | + } |
|---|
| 937 | + } |
|---|
| 938 | + break; |
|---|
| 939 | + |
|---|
| 940 | + case KBASE_MCU_HCTL_SHADERS_CORE_OFF_PEND: |
|---|
| 941 | + if (!shaders_trans && shaders_ready == backend->shaders_avail) { |
|---|
| 942 | + /* Cores now stable */ |
|---|
| 943 | + backend->pm_shaders_core_mask = shaders_ready; |
|---|
| 944 | + backend->mcu_state = KBASE_MCU_ON_HWCNT_ENABLE; |
|---|
| 945 | + } |
|---|
| 946 | + break; |
|---|
| 947 | + |
|---|
| 755 | 948 | case KBASE_MCU_ON_CORE_ATTR_UPDATE_PEND: |
|---|
| 756 | 949 | if (kbase_csf_firmware_core_attr_updated(kbdev)) { |
|---|
| 757 | | - backend->shaders_avail = |
|---|
| 758 | | - backend->shaders_desired_mask; |
|---|
| 950 | + backend->shaders_avail = backend->shaders_desired_mask; |
|---|
| 759 | 951 | backend->mcu_state = KBASE_MCU_ON; |
|---|
| 760 | 952 | } |
|---|
| 761 | 953 | break; |
|---|
| .. | .. |
|---|
| 770 | 962 | if (!backend->hwcnt_disabled) |
|---|
| 771 | 963 | kbase_pm_trigger_hwcnt_disable(kbdev); |
|---|
| 772 | 964 | |
|---|
| 773 | | - if (backend->hwcnt_disabled) |
|---|
| 965 | + |
|---|
| 966 | + if (backend->hwcnt_disabled) { |
|---|
| 967 | +#ifdef KBASE_PM_RUNTIME |
|---|
| 968 | + if (backend->gpu_sleep_mode_active) |
|---|
| 969 | + backend->mcu_state = KBASE_MCU_ON_SLEEP_INITIATE; |
|---|
| 970 | + else { |
|---|
| 971 | +#endif |
|---|
| 972 | + backend->mcu_state = KBASE_MCU_ON_HALT; |
|---|
| 973 | +#if IS_ENABLED(CONFIG_MALI_CORESIGHT) |
|---|
| 974 | + kbase_debug_coresight_csf_state_request( |
|---|
| 975 | + kbdev, KBASE_DEBUG_CORESIGHT_CSF_DISABLED); |
|---|
| 976 | + backend->mcu_state = KBASE_MCU_CORESIGHT_DISABLE; |
|---|
| 977 | +#endif /* IS_ENABLED(CONFIG_MALI_CORESIGHT) */ |
|---|
| 978 | + } |
|---|
| 979 | + } |
|---|
| 980 | + break; |
|---|
| 981 | + |
|---|
| 982 | +#if IS_ENABLED(CONFIG_MALI_CORESIGHT) |
|---|
| 983 | + case KBASE_MCU_ON_PMODE_ENTER_CORESIGHT_DISABLE: |
|---|
| 984 | + if (kbase_debug_coresight_csf_state_check( |
|---|
| 985 | + kbdev, KBASE_DEBUG_CORESIGHT_CSF_DISABLED)) { |
|---|
| 986 | + backend->mcu_state = KBASE_MCU_ON; |
|---|
| 987 | + kbdev->csf.coresight.disable_on_pmode_enter = false; |
|---|
| 988 | + } |
|---|
| 989 | + break; |
|---|
| 990 | + case KBASE_MCU_ON_PMODE_EXIT_CORESIGHT_ENABLE: |
|---|
| 991 | + if (kbase_debug_coresight_csf_state_check( |
|---|
| 992 | + kbdev, KBASE_DEBUG_CORESIGHT_CSF_ENABLED)) { |
|---|
| 993 | + backend->mcu_state = KBASE_MCU_ON; |
|---|
| 994 | + kbdev->csf.coresight.enable_on_pmode_exit = false; |
|---|
| 995 | + } |
|---|
| 996 | + break; |
|---|
| 997 | + case KBASE_MCU_CORESIGHT_DISABLE: |
|---|
| 998 | + if (kbase_debug_coresight_csf_state_check( |
|---|
| 999 | + kbdev, KBASE_DEBUG_CORESIGHT_CSF_DISABLED)) |
|---|
| 774 | 1000 | backend->mcu_state = KBASE_MCU_ON_HALT; |
|---|
| 775 | 1001 | break; |
|---|
| 1002 | + |
|---|
| 1003 | + case KBASE_MCU_CORESIGHT_ENABLE: |
|---|
| 1004 | + if (kbase_debug_coresight_csf_state_check( |
|---|
| 1005 | + kbdev, KBASE_DEBUG_CORESIGHT_CSF_ENABLED)) |
|---|
| 1006 | + backend->mcu_state = KBASE_MCU_ON_HWCNT_ENABLE; |
|---|
| 1007 | + break; |
|---|
| 1008 | +#endif /* IS_ENABLED(CONFIG_MALI_CORESIGHT) */ |
|---|
| 776 | 1009 | |
|---|
| 777 | 1010 | case KBASE_MCU_ON_HALT: |
|---|
| 778 | 1011 | if (!kbase_pm_is_mcu_desired(kbdev)) { |
|---|
| .. | .. |
|---|
| 784 | 1017 | |
|---|
| 785 | 1018 | case KBASE_MCU_ON_PEND_HALT: |
|---|
| 786 | 1019 | if (kbase_csf_firmware_mcu_halted(kbdev)) { |
|---|
| 1020 | + KBASE_KTRACE_ADD(kbdev, CSF_FIRMWARE_MCU_HALTED, NULL, |
|---|
| 1021 | + kbase_csf_ktrace_gpu_cycle_cnt(kbdev)); |
|---|
| 787 | 1022 | if (kbdev->csf.firmware_hctl_core_pwr) |
|---|
| 788 | 1023 | backend->mcu_state = |
|---|
| 789 | 1024 | KBASE_MCU_HCTL_SHADERS_READY_OFF; |
|---|
| .. | .. |
|---|
| 814 | 1049 | case KBASE_MCU_PEND_OFF: |
|---|
| 815 | 1050 | /* wait synchronously for the MCU to get disabled */ |
|---|
| 816 | 1051 | kbase_csf_firmware_disable_mcu_wait(kbdev); |
|---|
| 1052 | + if (!kbdev->csf.firmware_hctl_core_pwr) |
|---|
| 1053 | + kbasep_pm_toggle_power_interrupt(kbdev, true); |
|---|
| 817 | 1054 | backend->mcu_state = KBASE_MCU_OFF; |
|---|
| 818 | 1055 | break; |
|---|
| 1056 | +#ifdef KBASE_PM_RUNTIME |
|---|
| 1057 | + case KBASE_MCU_ON_SLEEP_INITIATE: |
|---|
| 1058 | + if (!kbase_pm_is_mcu_desired(kbdev)) { |
|---|
| 1059 | + kbase_csf_firmware_trigger_mcu_sleep(kbdev); |
|---|
| 1060 | + backend->mcu_state = KBASE_MCU_ON_PEND_SLEEP; |
|---|
| 1061 | + } else |
|---|
| 1062 | + backend->mcu_state = KBASE_MCU_ON_HWCNT_ENABLE; |
|---|
| 1063 | + break; |
|---|
| 819 | 1064 | |
|---|
| 1065 | + case KBASE_MCU_ON_PEND_SLEEP: |
|---|
| 1066 | + if (kbase_csf_firmware_is_mcu_in_sleep(kbdev)) { |
|---|
| 1067 | + KBASE_KTRACE_ADD(kbdev, CSF_FIRMWARE_MCU_SLEEP, NULL, |
|---|
| 1068 | + kbase_csf_ktrace_gpu_cycle_cnt(kbdev)); |
|---|
| 1069 | + backend->mcu_state = KBASE_MCU_IN_SLEEP; |
|---|
| 1070 | + kbase_pm_enable_db_mirror_interrupt(kbdev); |
|---|
| 1071 | + kbase_csf_scheduler_reval_idleness_post_sleep(kbdev); |
|---|
| 1072 | + /* Enable PM interrupt, after MCU has been put |
|---|
| 1073 | + * to sleep, for the power down of L2. |
|---|
| 1074 | + */ |
|---|
| 1075 | + if (!kbdev->csf.firmware_hctl_core_pwr) |
|---|
| 1076 | + kbasep_pm_toggle_power_interrupt(kbdev, true); |
|---|
| 1077 | + } |
|---|
| 1078 | + break; |
|---|
| 1079 | + |
|---|
| 1080 | + case KBASE_MCU_IN_SLEEP: |
|---|
| 1081 | + if (kbase_pm_is_mcu_desired(kbdev) && |
|---|
| 1082 | + backend->l2_state == KBASE_L2_ON) { |
|---|
| 1083 | + wait_mcu_as_inactive(kbdev); |
|---|
| 1084 | + KBASE_TLSTREAM_TL_KBASE_CSFFW_FW_REQUEST_WAKEUP( |
|---|
| 1085 | + kbdev, kbase_backend_get_cycle_cnt(kbdev)); |
|---|
| 1086 | + kbase_pm_enable_mcu_db_notification(kbdev); |
|---|
| 1087 | + kbase_pm_disable_db_mirror_interrupt(kbdev); |
|---|
| 1088 | + /* Disable PM interrupt after L2 has been |
|---|
| 1089 | + * powered up for the wakeup of MCU. |
|---|
| 1090 | + */ |
|---|
| 1091 | + if (!kbdev->csf.firmware_hctl_core_pwr) |
|---|
| 1092 | + kbasep_pm_toggle_power_interrupt(kbdev, false); |
|---|
| 1093 | + backend->mcu_state = KBASE_MCU_ON_HWCNT_ENABLE; |
|---|
| 1094 | + kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR); |
|---|
| 1095 | + } |
|---|
| 1096 | + break; |
|---|
| 1097 | +#endif |
|---|
| 820 | 1098 | case KBASE_MCU_RESET_WAIT: |
|---|
| 821 | 1099 | /* Reset complete */ |
|---|
| 822 | 1100 | if (!backend->in_reset) |
|---|
| 823 | 1101 | backend->mcu_state = KBASE_MCU_OFF; |
|---|
| 1102 | + |
|---|
| 1103 | +#if IS_ENABLED(CONFIG_MALI_CORESIGHT) |
|---|
| 1104 | + kbdev->csf.coresight.disable_on_pmode_enter = false; |
|---|
| 1105 | + kbdev->csf.coresight.enable_on_pmode_exit = false; |
|---|
| 1106 | +#endif /* IS_ENABLED(CONFIG_MALI_CORESIGHT) */ |
|---|
| 824 | 1107 | break; |
|---|
| 825 | 1108 | |
|---|
| 826 | 1109 | default: |
|---|
| .. | .. |
|---|
| 828 | 1111 | backend->mcu_state); |
|---|
| 829 | 1112 | } |
|---|
| 830 | 1113 | |
|---|
| 831 | | - if (backend->mcu_state != prev_state) |
|---|
| 1114 | + if (backend->mcu_state != prev_state) { |
|---|
| 832 | 1115 | dev_dbg(kbdev->dev, "MCU state transition: %s to %s\n", |
|---|
| 833 | 1116 | kbase_mcu_state_to_string(prev_state), |
|---|
| 834 | 1117 | kbase_mcu_state_to_string(backend->mcu_state)); |
|---|
| 1118 | + kbase_ktrace_log_mcu_state(kbdev, backend->mcu_state); |
|---|
| 1119 | + } |
|---|
| 835 | 1120 | |
|---|
| 836 | 1121 | } while (backend->mcu_state != prev_state); |
|---|
| 837 | 1122 | |
|---|
| 838 | 1123 | return 0; |
|---|
| 1124 | +} |
|---|
| 1125 | + |
|---|
| 1126 | +static void core_idle_worker(struct work_struct *work) |
|---|
| 1127 | +{ |
|---|
| 1128 | + struct kbase_device *kbdev = |
|---|
| 1129 | + container_of(work, struct kbase_device, pm.backend.core_idle_work); |
|---|
| 1130 | + struct kbase_pm_backend_data *backend = &kbdev->pm.backend; |
|---|
| 1131 | + unsigned long flags; |
|---|
| 1132 | + |
|---|
| 1133 | + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); |
|---|
| 1134 | + while (backend->gpu_powered && (backend->mcu_state == KBASE_MCU_HCTL_CORE_INACTIVE_PEND)) { |
|---|
| 1135 | + const unsigned int core_inactive_wait_ms = 1; |
|---|
| 1136 | + u64 active_cores = kbase_pm_get_active_cores(kbdev, KBASE_PM_CORE_SHADER); |
|---|
| 1137 | + u64 shaders_ready = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER); |
|---|
| 1138 | + u64 cores_to_disable = shaders_ready & ~backend->shaders_desired_mask; |
|---|
| 1139 | + |
|---|
| 1140 | + if (!(cores_to_disable & active_cores)) { |
|---|
| 1141 | + kbase_pm_update_state(kbdev); |
|---|
| 1142 | + break; |
|---|
| 1143 | + } |
|---|
| 1144 | + |
|---|
| 1145 | + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); |
|---|
| 1146 | + msleep(core_inactive_wait_ms); |
|---|
| 1147 | + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); |
|---|
| 1148 | + } |
|---|
| 1149 | + |
|---|
| 1150 | + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); |
|---|
| 839 | 1151 | } |
|---|
| 840 | 1152 | #endif |
|---|
| 841 | 1153 | |
|---|
| .. | .. |
|---|
| 852 | 1164 | return strings[state]; |
|---|
| 853 | 1165 | } |
|---|
| 854 | 1166 | |
|---|
| 1167 | +static |
|---|
| 1168 | +void kbase_ktrace_log_l2_core_state(struct kbase_device *kbdev, enum kbase_l2_core_state state) |
|---|
| 1169 | +{ |
|---|
| 1170 | +#if KBASE_KTRACE_ENABLE |
|---|
| 1171 | + switch (state) { |
|---|
| 1172 | +#define KBASEP_L2_STATE(n) \ |
|---|
| 1173 | + case KBASE_L2_ ## n: \ |
|---|
| 1174 | + KBASE_KTRACE_ADD(kbdev, PM_L2_ ## n, NULL, state); \ |
|---|
| 1175 | + break; |
|---|
| 1176 | +#include "mali_kbase_pm_l2_states.h" |
|---|
| 1177 | +#undef KBASEP_L2_STATE |
|---|
| 1178 | + } |
|---|
| 1179 | +#endif |
|---|
| 1180 | +} |
|---|
| 1181 | + |
|---|
| 1182 | +#if !MALI_USE_CSF |
|---|
| 1183 | +/* On powering on the L2, the tracked kctx becomes stale and can be cleared. |
|---|
| 1184 | + * This enables the backend to spare the START_FLUSH.INV_SHADER_OTHER |
|---|
| 1185 | + * operation on the first submitted katom after the L2 powering on. |
|---|
| 1186 | + */ |
|---|
| 1187 | +static void kbase_pm_l2_clear_backend_slot_submit_kctx(struct kbase_device *kbdev) |
|---|
| 1188 | +{ |
|---|
| 1189 | + int js; |
|---|
| 1190 | + |
|---|
| 1191 | + lockdep_assert_held(&kbdev->hwaccess_lock); |
|---|
| 1192 | + |
|---|
| 1193 | + /* Clear the slots' last katom submission kctx */ |
|---|
| 1194 | + for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) |
|---|
| 1195 | + kbdev->hwaccess.backend.slot_rb[js].last_kctx_tagged = SLOT_RB_NULL_TAG_VAL; |
|---|
| 1196 | +} |
|---|
| 1197 | +#endif |
|---|
| 1198 | + |
|---|
| 1199 | +static bool can_power_down_l2(struct kbase_device *kbdev) |
|---|
| 1200 | +{ |
|---|
| 1201 | +#if MALI_USE_CSF |
|---|
| 1202 | + /* Due to the HW issue GPU2019-3878, need to prevent L2 power off |
|---|
| 1203 | + * whilst MMU command is in progress. |
|---|
| 1204 | + * Also defer the power-down if MMU is in process of page migration. |
|---|
| 1205 | + */ |
|---|
| 1206 | + return !kbdev->mmu_hw_operation_in_progress && !kbdev->mmu_page_migrate_in_progress; |
|---|
| 1207 | +#else |
|---|
| 1208 | + return !kbdev->mmu_page_migrate_in_progress; |
|---|
| 1209 | +#endif |
|---|
| 1210 | +} |
|---|
| 1211 | + |
|---|
| 1212 | +static bool can_power_up_l2(struct kbase_device *kbdev) |
|---|
| 1213 | +{ |
|---|
| 1214 | + lockdep_assert_held(&kbdev->hwaccess_lock); |
|---|
| 1215 | + |
|---|
| 1216 | + /* Avoiding l2 transition if MMU is undergoing page migration */ |
|---|
| 1217 | + return !kbdev->mmu_page_migrate_in_progress; |
|---|
| 1218 | +} |
|---|
| 1219 | + |
|---|
| 1220 | +static bool need_tiler_control(struct kbase_device *kbdev) |
|---|
| 1221 | +{ |
|---|
| 1222 | +#if MALI_USE_CSF |
|---|
| 1223 | + if (kbase_pm_no_mcu_core_pwroff(kbdev)) |
|---|
| 1224 | + return true; |
|---|
| 1225 | + else |
|---|
| 1226 | + return false; |
|---|
| 1227 | +#else |
|---|
| 1228 | + return true; |
|---|
| 1229 | +#endif |
|---|
| 1230 | +} |
|---|
| 1231 | + |
|---|
| 855 | 1232 | static int kbase_pm_l2_update_state(struct kbase_device *kbdev) |
|---|
| 856 | 1233 | { |
|---|
| 857 | 1234 | struct kbase_pm_backend_data *backend = &kbdev->pm.backend; |
|---|
| 858 | 1235 | u64 l2_present = kbdev->gpu_props.curr_config.l2_present; |
|---|
| 859 | | -#if !MALI_USE_CSF |
|---|
| 860 | 1236 | u64 tiler_present = kbdev->gpu_props.props.raw_props.tiler_present; |
|---|
| 861 | | -#endif |
|---|
| 1237 | + bool l2_power_up_done; |
|---|
| 862 | 1238 | enum kbase_l2_core_state prev_state; |
|---|
| 863 | 1239 | |
|---|
| 864 | 1240 | lockdep_assert_held(&kbdev->hwaccess_lock); |
|---|
| .. | .. |
|---|
| 870 | 1246 | u64 l2_ready = kbase_pm_get_ready_cores(kbdev, |
|---|
| 871 | 1247 | KBASE_PM_CORE_L2); |
|---|
| 872 | 1248 | |
|---|
| 873 | | -#if !MALI_USE_CSF |
|---|
| 874 | | - u64 tiler_trans = kbase_pm_get_trans_cores(kbdev, |
|---|
| 875 | | - KBASE_PM_CORE_TILER); |
|---|
| 876 | | - u64 tiler_ready = kbase_pm_get_ready_cores(kbdev, |
|---|
| 877 | | - KBASE_PM_CORE_TILER); |
|---|
| 878 | | -#endif |
|---|
| 879 | | - |
|---|
| 1249 | +#ifdef CONFIG_MALI_ARBITER_SUPPORT |
|---|
| 880 | 1250 | /* |
|---|
| 881 | 1251 | * kbase_pm_get_ready_cores and kbase_pm_get_trans_cores |
|---|
| 882 | 1252 | * are vulnerable to corruption if gpu is lost |
|---|
| 883 | 1253 | */ |
|---|
| 884 | | - if (kbase_is_gpu_removed(kbdev) |
|---|
| 885 | | -#ifdef CONFIG_MALI_ARBITER_SUPPORT |
|---|
| 886 | | - || kbase_pm_is_gpu_lost(kbdev)) { |
|---|
| 887 | | -#else |
|---|
| 888 | | - ) { |
|---|
| 889 | | -#endif |
|---|
| 1254 | + if (kbase_is_gpu_removed(kbdev) || kbase_pm_is_gpu_lost(kbdev)) { |
|---|
| 890 | 1255 | backend->shaders_state = |
|---|
| 891 | 1256 | KBASE_SHADERS_OFF_CORESTACK_OFF; |
|---|
| 892 | | - backend->l2_state = KBASE_L2_OFF; |
|---|
| 893 | | - dev_dbg(kbdev->dev, "GPU lost has occurred - L2 off\n"); |
|---|
| 1257 | + backend->hwcnt_desired = false; |
|---|
| 1258 | + if (!backend->hwcnt_disabled) { |
|---|
| 1259 | + /* Don't progress until hw counters are disabled |
|---|
| 1260 | + * This may involve waiting for a worker to complete. |
|---|
| 1261 | + * The HW counters backend disable code checks for the |
|---|
| 1262 | + * GPU removed case and will error out without touching |
|---|
| 1263 | + * the hardware. This step is needed to keep the HW |
|---|
| 1264 | + * counters in a consistent state after a GPU lost. |
|---|
| 1265 | + */ |
|---|
| 1266 | + backend->l2_state = |
|---|
| 1267 | + KBASE_L2_ON_HWCNT_DISABLE; |
|---|
| 1268 | + KBASE_KTRACE_ADD(kbdev, PM_L2_ON_HWCNT_DISABLE, NULL, |
|---|
| 1269 | + backend->l2_state); |
|---|
| 1270 | + kbase_pm_trigger_hwcnt_disable(kbdev); |
|---|
| 1271 | + } |
|---|
| 1272 | + |
|---|
| 1273 | + if (backend->hwcnt_disabled) { |
|---|
| 1274 | + backend->l2_state = KBASE_L2_OFF; |
|---|
| 1275 | + KBASE_KTRACE_ADD(kbdev, PM_L2_OFF, NULL, backend->l2_state); |
|---|
| 1276 | + dev_dbg(kbdev->dev, "GPU lost has occurred - L2 off\n"); |
|---|
| 1277 | + } |
|---|
| 894 | 1278 | break; |
|---|
| 895 | 1279 | } |
|---|
| 1280 | +#endif |
|---|
| 896 | 1281 | |
|---|
| 897 | 1282 | /* mask off ready from trans in case transitions finished |
|---|
| 898 | 1283 | * between the register reads |
|---|
| 899 | 1284 | */ |
|---|
| 900 | 1285 | l2_trans &= ~l2_ready; |
|---|
| 901 | | -#if !MALI_USE_CSF |
|---|
| 902 | | - tiler_trans &= ~tiler_ready; |
|---|
| 903 | | -#endif |
|---|
| 1286 | + |
|---|
| 904 | 1287 | prev_state = backend->l2_state; |
|---|
| 905 | 1288 | |
|---|
| 906 | 1289 | switch (backend->l2_state) { |
|---|
| 907 | 1290 | case KBASE_L2_OFF: |
|---|
| 908 | | - if (kbase_pm_is_l2_desired(kbdev)) { |
|---|
| 1291 | + if (kbase_pm_is_l2_desired(kbdev) && can_power_up_l2(kbdev)) { |
|---|
| 1292 | +#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) |
|---|
| 1293 | + /* Enable HW timer of IPA control before |
|---|
| 1294 | + * L2 cache is powered-up. |
|---|
| 1295 | + */ |
|---|
| 1296 | + kbase_ipa_control_handle_gpu_sleep_exit(kbdev); |
|---|
| 1297 | +#endif |
|---|
| 909 | 1298 | /* |
|---|
| 910 | 1299 | * Set the desired config for L2 before |
|---|
| 911 | 1300 | * powering it on |
|---|
| 912 | 1301 | */ |
|---|
| 913 | 1302 | kbase_pm_l2_config_override(kbdev); |
|---|
| 914 | | -#if !MALI_USE_CSF |
|---|
| 915 | | - /* L2 is required, power on. Powering on the |
|---|
| 916 | | - * tiler will also power the first L2 cache. |
|---|
| 917 | | - */ |
|---|
| 918 | | - kbase_pm_invoke(kbdev, KBASE_PM_CORE_TILER, |
|---|
| 919 | | - tiler_present, ACTION_PWRON); |
|---|
| 1303 | + kbase_pbha_write_settings(kbdev); |
|---|
| 920 | 1304 | |
|---|
| 1305 | + /* If Host is controlling the power for shader |
|---|
| 1306 | + * cores, then it also needs to control the |
|---|
| 1307 | + * power for Tiler. |
|---|
| 1308 | + * Powering on the tiler will also power the |
|---|
| 1309 | + * L2 cache. |
|---|
| 1310 | + */ |
|---|
| 1311 | + if (need_tiler_control(kbdev)) { |
|---|
| 1312 | + kbase_pm_invoke(kbdev, KBASE_PM_CORE_TILER, tiler_present, |
|---|
| 1313 | + ACTION_PWRON); |
|---|
| 1314 | + } else { |
|---|
| 1315 | + kbase_pm_invoke(kbdev, KBASE_PM_CORE_L2, l2_present, |
|---|
| 1316 | + ACTION_PWRON); |
|---|
| 1317 | + } |
|---|
| 1318 | +#if !MALI_USE_CSF |
|---|
| 921 | 1319 | /* If we have more than one L2 cache then we |
|---|
| 922 | 1320 | * must power them on explicitly. |
|---|
| 923 | 1321 | */ |
|---|
| .. | .. |
|---|
| 925 | 1323 | kbase_pm_invoke(kbdev, KBASE_PM_CORE_L2, |
|---|
| 926 | 1324 | l2_present & ~1, |
|---|
| 927 | 1325 | ACTION_PWRON); |
|---|
| 928 | | -#else |
|---|
| 929 | | - /* With CSF firmware, Host driver doesn't need to |
|---|
| 930 | | - * handle power management with both shader and tiler cores. |
|---|
| 931 | | - * The CSF firmware will power up the cores appropriately. |
|---|
| 932 | | - * So only power the l2 cache explicitly. |
|---|
| 933 | | - */ |
|---|
| 934 | | - kbase_pm_invoke(kbdev, KBASE_PM_CORE_L2, |
|---|
| 935 | | - l2_present, ACTION_PWRON); |
|---|
| 1326 | + /* Clear backend slot submission kctx */ |
|---|
| 1327 | + kbase_pm_l2_clear_backend_slot_submit_kctx(kbdev); |
|---|
| 936 | 1328 | #endif |
|---|
| 937 | 1329 | backend->l2_state = KBASE_L2_PEND_ON; |
|---|
| 938 | 1330 | } |
|---|
| 939 | 1331 | break; |
|---|
| 940 | 1332 | |
|---|
| 941 | 1333 | case KBASE_L2_PEND_ON: |
|---|
| 942 | | -#if !MALI_USE_CSF |
|---|
| 943 | | - if (!l2_trans && l2_ready == l2_present && !tiler_trans |
|---|
| 944 | | - && tiler_ready == tiler_present) { |
|---|
| 945 | | - KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_TILER, NULL, |
|---|
| 946 | | - tiler_ready); |
|---|
| 947 | | -#else |
|---|
| 1334 | + l2_power_up_done = false; |
|---|
| 948 | 1335 | if (!l2_trans && l2_ready == l2_present) { |
|---|
| 949 | | - KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_L2, NULL, |
|---|
| 950 | | - l2_ready); |
|---|
| 951 | | -#endif |
|---|
| 1336 | + if (need_tiler_control(kbdev)) { |
|---|
| 1337 | + u64 tiler_trans = kbase_pm_get_trans_cores( |
|---|
| 1338 | + kbdev, KBASE_PM_CORE_TILER); |
|---|
| 1339 | + u64 tiler_ready = kbase_pm_get_ready_cores( |
|---|
| 1340 | + kbdev, KBASE_PM_CORE_TILER); |
|---|
| 1341 | + tiler_trans &= ~tiler_ready; |
|---|
| 1342 | + |
|---|
| 1343 | + if (!tiler_trans && tiler_ready == tiler_present) { |
|---|
| 1344 | + KBASE_KTRACE_ADD(kbdev, |
|---|
| 1345 | + PM_CORES_CHANGE_AVAILABLE_TILER, |
|---|
| 1346 | + NULL, tiler_ready); |
|---|
| 1347 | + l2_power_up_done = true; |
|---|
| 1348 | + } |
|---|
| 1349 | + } else { |
|---|
| 1350 | + KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_L2, NULL, |
|---|
| 1351 | + l2_ready); |
|---|
| 1352 | + l2_power_up_done = true; |
|---|
| 1353 | + } |
|---|
| 1354 | + } |
|---|
| 1355 | + if (l2_power_up_done) { |
|---|
| 952 | 1356 | /* |
|---|
| 953 | 1357 | * Ensure snoops are enabled after L2 is powered |
|---|
| 954 | 1358 | * up. Note that kbase keeps track of the snoop |
|---|
| .. | .. |
|---|
| 1027 | 1431 | break; |
|---|
| 1028 | 1432 | #else |
|---|
| 1029 | 1433 | /* Do not power off L2 until the MCU has been stopped */ |
|---|
| 1030 | | - if (backend->mcu_state != KBASE_MCU_OFF) |
|---|
| 1434 | + if ((backend->mcu_state != KBASE_MCU_OFF) && |
|---|
| 1435 | + (backend->mcu_state != KBASE_MCU_IN_SLEEP)) |
|---|
| 1031 | 1436 | break; |
|---|
| 1032 | 1437 | #endif |
|---|
| 1033 | 1438 | |
|---|
| .. | .. |
|---|
| 1073 | 1478 | } |
|---|
| 1074 | 1479 | |
|---|
| 1075 | 1480 | backend->hwcnt_desired = false; |
|---|
| 1076 | | - if (!backend->hwcnt_disabled) { |
|---|
| 1481 | + if (!backend->hwcnt_disabled) |
|---|
| 1077 | 1482 | kbase_pm_trigger_hwcnt_disable(kbdev); |
|---|
| 1078 | | - } |
|---|
| 1079 | 1483 | #endif |
|---|
| 1080 | 1484 | |
|---|
| 1081 | 1485 | if (backend->hwcnt_disabled) { |
|---|
| .. | .. |
|---|
| 1112 | 1516 | break; |
|---|
| 1113 | 1517 | |
|---|
| 1114 | 1518 | case KBASE_L2_POWER_DOWN: |
|---|
| 1115 | | - if (!backend->l2_always_on) |
|---|
| 1116 | | - /* Powering off the L2 will also power off the |
|---|
| 1117 | | - * tiler. |
|---|
| 1118 | | - */ |
|---|
| 1119 | | - kbase_pm_invoke(kbdev, KBASE_PM_CORE_L2, |
|---|
| 1120 | | - l2_present, |
|---|
| 1121 | | - ACTION_PWROFF); |
|---|
| 1122 | | - else |
|---|
| 1123 | | - /* If L2 cache is powered then we must flush it |
|---|
| 1124 | | - * before we power off the GPU. Normally this |
|---|
| 1125 | | - * would have been handled when the L2 was |
|---|
| 1126 | | - * powered off. |
|---|
| 1127 | | - */ |
|---|
| 1128 | | - kbase_gpu_start_cache_clean_nolock( |
|---|
| 1129 | | - kbdev); |
|---|
| 1519 | + if (kbase_pm_is_l2_desired(kbdev)) |
|---|
| 1520 | + backend->l2_state = KBASE_L2_PEND_ON; |
|---|
| 1521 | + else if (can_power_down_l2(kbdev)) { |
|---|
| 1522 | + if (!backend->l2_always_on) |
|---|
| 1523 | + /* Powering off the L2 will also power off the |
|---|
| 1524 | + * tiler. |
|---|
| 1525 | + */ |
|---|
| 1526 | + kbase_pm_invoke(kbdev, KBASE_PM_CORE_L2, |
|---|
| 1527 | + l2_present, |
|---|
| 1528 | + ACTION_PWROFF); |
|---|
| 1529 | + else |
|---|
| 1530 | + /* If L2 cache is powered then we must flush it |
|---|
| 1531 | + * before we power off the GPU. Normally this |
|---|
| 1532 | + * would have been handled when the L2 was |
|---|
| 1533 | + * powered off. |
|---|
| 1534 | + */ |
|---|
| 1535 | + kbase_gpu_start_cache_clean_nolock( |
|---|
| 1536 | + kbdev, GPU_COMMAND_CACHE_CLN_INV_L2); |
|---|
| 1130 | 1537 | #if !MALI_USE_CSF |
|---|
| 1131 | | - KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_TILER, NULL, 0u); |
|---|
| 1538 | + KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_TILER, NULL, 0u); |
|---|
| 1132 | 1539 | #else |
|---|
| 1133 | | - KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_L2, NULL, 0u); |
|---|
| 1540 | + KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_L2, NULL, 0u); |
|---|
| 1134 | 1541 | #endif |
|---|
| 1135 | | - backend->l2_state = KBASE_L2_PEND_OFF; |
|---|
| 1542 | + backend->l2_state = KBASE_L2_PEND_OFF; |
|---|
| 1543 | + } |
|---|
| 1136 | 1544 | break; |
|---|
| 1137 | 1545 | |
|---|
| 1138 | 1546 | case KBASE_L2_PEND_OFF: |
|---|
| .. | .. |
|---|
| 1140 | 1548 | /* We only need to check the L2 here - if the L2 |
|---|
| 1141 | 1549 | * is off then the tiler is definitely also off. |
|---|
| 1142 | 1550 | */ |
|---|
| 1143 | | - if (!l2_trans && !l2_ready) |
|---|
| 1551 | + if (!l2_trans && !l2_ready) { |
|---|
| 1552 | +#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) |
|---|
| 1553 | + /* Allow clock gating within the GPU and prevent it |
|---|
| 1554 | + * from being seen as active during sleep. |
|---|
| 1555 | + */ |
|---|
| 1556 | + kbase_ipa_control_handle_gpu_sleep_enter(kbdev); |
|---|
| 1557 | +#endif |
|---|
| 1144 | 1558 | /* L2 is now powered off */ |
|---|
| 1145 | 1559 | backend->l2_state = KBASE_L2_OFF; |
|---|
| 1560 | + } |
|---|
| 1146 | 1561 | } else { |
|---|
| 1147 | | - if (!kbdev->cache_clean_in_progress) |
|---|
| 1562 | + if (!kbdev->cache_clean_in_progress) { |
|---|
| 1563 | +#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) |
|---|
| 1564 | + /* Allow clock gating within the GPU and prevent it |
|---|
| 1565 | + * from being seen as active during sleep. |
|---|
| 1566 | + */ |
|---|
| 1567 | + kbase_ipa_control_handle_gpu_sleep_enter(kbdev); |
|---|
| 1568 | +#endif |
|---|
| 1148 | 1569 | backend->l2_state = KBASE_L2_OFF; |
|---|
| 1570 | + } |
|---|
| 1149 | 1571 | } |
|---|
| 1150 | 1572 | break; |
|---|
| 1151 | 1573 | |
|---|
| .. | .. |
|---|
| 1160 | 1582 | backend->l2_state); |
|---|
| 1161 | 1583 | } |
|---|
| 1162 | 1584 | |
|---|
| 1163 | | - if (backend->l2_state != prev_state) |
|---|
| 1585 | + if (backend->l2_state != prev_state) { |
|---|
| 1164 | 1586 | dev_dbg(kbdev->dev, "L2 state transition: %s to %s\n", |
|---|
| 1165 | 1587 | kbase_l2_core_state_to_string(prev_state), |
|---|
| 1166 | 1588 | kbase_l2_core_state_to_string( |
|---|
| 1167 | 1589 | backend->l2_state)); |
|---|
| 1590 | + kbase_ktrace_log_l2_core_state(kbdev, backend->l2_state); |
|---|
| 1591 | + } |
|---|
| 1168 | 1592 | |
|---|
| 1169 | 1593 | } while (backend->l2_state != prev_state); |
|---|
| 1170 | 1594 | |
|---|
| .. | .. |
|---|
| 1503 | 1927 | break; |
|---|
| 1504 | 1928 | |
|---|
| 1505 | 1929 | case KBASE_SHADERS_WAIT_FINISHED_CORESTACK_ON: |
|---|
| 1506 | | - shader_poweroff_timer_queue_cancel(kbdev); |
|---|
| 1930 | + if (!backend->partial_shaderoff) |
|---|
| 1931 | + shader_poweroff_timer_queue_cancel(kbdev); |
|---|
| 1507 | 1932 | |
|---|
| 1508 | 1933 | if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TTRX_921)) { |
|---|
| 1509 | | - kbase_gpu_start_cache_clean_nolock(kbdev); |
|---|
| 1934 | + kbase_gpu_start_cache_clean_nolock( |
|---|
| 1935 | + kbdev, GPU_COMMAND_CACHE_CLN_INV_L2); |
|---|
| 1510 | 1936 | backend->shaders_state = |
|---|
| 1511 | 1937 | KBASE_SHADERS_L2_FLUSHING_CORESTACK_ON; |
|---|
| 1512 | 1938 | } else { |
|---|
| .. | .. |
|---|
| 1608 | 2034 | |
|---|
| 1609 | 2035 | return 0; |
|---|
| 1610 | 2036 | } |
|---|
| 1611 | | -#endif |
|---|
| 2037 | +#endif /* !MALI_USE_CSF */ |
|---|
| 1612 | 2038 | |
|---|
| 1613 | 2039 | static bool kbase_pm_is_in_desired_state_nolock(struct kbase_device *kbdev) |
|---|
| 1614 | 2040 | { |
|---|
| .. | .. |
|---|
| 1616 | 2042 | |
|---|
| 1617 | 2043 | lockdep_assert_held(&kbdev->hwaccess_lock); |
|---|
| 1618 | 2044 | |
|---|
| 1619 | | - if (kbase_pm_is_l2_desired(kbdev) && |
|---|
| 1620 | | - kbdev->pm.backend.l2_state != KBASE_L2_ON) |
|---|
| 1621 | | - in_desired_state = false; |
|---|
| 1622 | | - else if (!kbase_pm_is_l2_desired(kbdev) && |
|---|
| 1623 | | - kbdev->pm.backend.l2_state != KBASE_L2_OFF) |
|---|
| 1624 | | - in_desired_state = false; |
|---|
| 2045 | + in_desired_state = kbase_pm_l2_is_in_desired_state(kbdev); |
|---|
| 1625 | 2046 | |
|---|
| 1626 | 2047 | #if !MALI_USE_CSF |
|---|
| 1627 | 2048 | if (kbdev->pm.backend.shaders_desired && |
|---|
| .. | .. |
|---|
| 1631 | 2052 | kbdev->pm.backend.shaders_state != KBASE_SHADERS_OFF_CORESTACK_OFF) |
|---|
| 1632 | 2053 | in_desired_state = false; |
|---|
| 1633 | 2054 | #else |
|---|
| 1634 | | - if (kbase_pm_is_mcu_desired(kbdev) && |
|---|
| 1635 | | - kbdev->pm.backend.mcu_state != KBASE_MCU_ON) |
|---|
| 1636 | | - in_desired_state = false; |
|---|
| 1637 | | - else if (!kbase_pm_is_mcu_desired(kbdev) && |
|---|
| 1638 | | - kbdev->pm.backend.mcu_state != KBASE_MCU_OFF) |
|---|
| 1639 | | - in_desired_state = false; |
|---|
| 2055 | + in_desired_state &= kbase_pm_mcu_is_in_desired_state(kbdev); |
|---|
| 1640 | 2056 | #endif |
|---|
| 1641 | 2057 | |
|---|
| 1642 | 2058 | return in_desired_state; |
|---|
| .. | .. |
|---|
| 1734 | 2150 | if (kbase_pm_mcu_update_state(kbdev)) |
|---|
| 1735 | 2151 | return; |
|---|
| 1736 | 2152 | |
|---|
| 1737 | | - if (prev_mcu_state != KBASE_MCU_OFF && |
|---|
| 1738 | | - kbdev->pm.backend.mcu_state == KBASE_MCU_OFF) { |
|---|
| 2153 | + if (!kbase_pm_is_mcu_inactive(kbdev, prev_mcu_state) && |
|---|
| 2154 | + kbase_pm_is_mcu_inactive(kbdev, kbdev->pm.backend.mcu_state)) { |
|---|
| 1739 | 2155 | if (kbase_pm_l2_update_state(kbdev)) |
|---|
| 1740 | 2156 | return; |
|---|
| 1741 | 2157 | } |
|---|
| .. | .. |
|---|
| 1803 | 2219 | stt->default_ticks = DEFAULT_PM_POWEROFF_TICK_SHADER; |
|---|
| 1804 | 2220 | stt->configured_ticks = stt->default_ticks; |
|---|
| 1805 | 2221 | |
|---|
| 2222 | +#if MALI_USE_CSF |
|---|
| 2223 | + kbdev->pm.backend.core_idle_wq = alloc_workqueue("coreoff_wq", WQ_HIGHPRI | WQ_UNBOUND, 1); |
|---|
| 2224 | + if (!kbdev->pm.backend.core_idle_wq) { |
|---|
| 2225 | + destroy_workqueue(stt->wq); |
|---|
| 2226 | + return -ENOMEM; |
|---|
| 2227 | + } |
|---|
| 2228 | + |
|---|
| 2229 | + INIT_WORK(&kbdev->pm.backend.core_idle_work, core_idle_worker); |
|---|
| 2230 | +#endif |
|---|
| 2231 | + |
|---|
| 1806 | 2232 | return 0; |
|---|
| 1807 | 2233 | } |
|---|
| 1808 | 2234 | |
|---|
| 1809 | 2235 | void kbase_pm_state_machine_term(struct kbase_device *kbdev) |
|---|
| 1810 | 2236 | { |
|---|
| 2237 | +#if MALI_USE_CSF |
|---|
| 2238 | + destroy_workqueue(kbdev->pm.backend.core_idle_wq); |
|---|
| 2239 | +#endif |
|---|
| 1811 | 2240 | hrtimer_cancel(&kbdev->pm.backend.shader_tick_timer.timer); |
|---|
| 1812 | 2241 | destroy_workqueue(kbdev->pm.backend.shader_tick_timer.wq); |
|---|
| 1813 | 2242 | } |
|---|
| .. | .. |
|---|
| 1820 | 2249 | |
|---|
| 1821 | 2250 | backend->in_reset = true; |
|---|
| 1822 | 2251 | backend->l2_state = KBASE_L2_RESET_WAIT; |
|---|
| 2252 | + KBASE_KTRACE_ADD(kbdev, PM_L2_RESET_WAIT, NULL, backend->l2_state); |
|---|
| 1823 | 2253 | #if !MALI_USE_CSF |
|---|
| 1824 | 2254 | backend->shaders_state = KBASE_SHADERS_RESET_WAIT; |
|---|
| 1825 | 2255 | #else |
|---|
| .. | .. |
|---|
| 1828 | 2258 | */ |
|---|
| 1829 | 2259 | if (likely(kbdev->csf.firmware_inited)) { |
|---|
| 1830 | 2260 | backend->mcu_state = KBASE_MCU_RESET_WAIT; |
|---|
| 2261 | + KBASE_KTRACE_ADD(kbdev, PM_MCU_RESET_WAIT, NULL, backend->mcu_state); |
|---|
| 2262 | +#ifdef KBASE_PM_RUNTIME |
|---|
| 2263 | + backend->exit_gpu_sleep_mode = true; |
|---|
| 2264 | +#endif |
|---|
| 1831 | 2265 | kbdev->csf.firmware_reload_needed = true; |
|---|
| 1832 | 2266 | } else { |
|---|
| 1833 | 2267 | WARN_ON(backend->mcu_state != KBASE_MCU_OFF); |
|---|
| .. | .. |
|---|
| 1865 | 2299 | */ |
|---|
| 1866 | 2300 | kbase_gpu_cache_clean_wait_complete(kbdev); |
|---|
| 1867 | 2301 | backend->in_reset = false; |
|---|
| 2302 | +#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) |
|---|
| 2303 | + backend->gpu_wakeup_override = false; |
|---|
| 2304 | +#endif |
|---|
| 1868 | 2305 | kbase_pm_update_state(kbdev); |
|---|
| 1869 | 2306 | |
|---|
| 1870 | 2307 | spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); |
|---|
| 1871 | 2308 | } |
|---|
| 1872 | 2309 | |
|---|
| 1873 | | -/* Timeout for kbase_pm_wait_for_desired_state when wait_event_killable has |
|---|
| 1874 | | - * aborted due to a fatal signal. If the time spent waiting has exceeded this |
|---|
| 1875 | | - * threshold then there is most likely a hardware issue. |
|---|
| 2310 | +#if !MALI_USE_CSF |
|---|
| 2311 | +/* Timeout in milliseconds for GPU Power Management to reach the desired |
|---|
| 2312 | + * Shader and L2 state. If the time spent waiting has exceeded this threshold |
|---|
| 2313 | + * then there is most likely a hardware issue. |
|---|
| 1876 | 2314 | */ |
|---|
| 1877 | 2315 | #define PM_TIMEOUT_MS (5000) /* 5s */ |
|---|
| 2316 | +#endif |
|---|
| 1878 | 2317 | |
|---|
| 1879 | 2318 | static void kbase_pm_timed_out(struct kbase_device *kbdev) |
|---|
| 1880 | 2319 | { |
|---|
| .. | .. |
|---|
| 1949 | 2388 | spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); |
|---|
| 1950 | 2389 | |
|---|
| 1951 | 2390 | #if MALI_USE_CSF |
|---|
| 1952 | | - timeout = kbase_csf_timeout_in_jiffies(PM_TIMEOUT_MS); |
|---|
| 2391 | + timeout = kbase_csf_timeout_in_jiffies(kbase_get_timeout_ms(kbdev, CSF_PM_TIMEOUT)); |
|---|
| 1953 | 2392 | #else |
|---|
| 1954 | 2393 | timeout = msecs_to_jiffies(PM_TIMEOUT_MS); |
|---|
| 1955 | 2394 | #endif |
|---|
| 1956 | 2395 | |
|---|
| 1957 | 2396 | /* Wait for cores */ |
|---|
| 1958 | 2397 | #if KERNEL_VERSION(4, 13, 1) <= LINUX_VERSION_CODE |
|---|
| 1959 | | - remaining = wait_event_killable_timeout( |
|---|
| 2398 | + remaining = wait_event_killable_timeout(kbdev->pm.backend.gpu_in_desired_state_wait, |
|---|
| 2399 | + kbase_pm_is_in_desired_state_with_l2_powered(kbdev), |
|---|
| 2400 | + timeout); |
|---|
| 1960 | 2401 | #else |
|---|
| 1961 | 2402 | remaining = wait_event_timeout( |
|---|
| 1962 | | -#endif |
|---|
| 1963 | 2403 | kbdev->pm.backend.gpu_in_desired_state_wait, |
|---|
| 1964 | 2404 | kbase_pm_is_in_desired_state_with_l2_powered(kbdev), timeout); |
|---|
| 2405 | +#endif |
|---|
| 1965 | 2406 | |
|---|
| 1966 | 2407 | if (!remaining) { |
|---|
| 1967 | 2408 | kbase_pm_timed_out(kbdev); |
|---|
| .. | .. |
|---|
| 1981 | 2422 | unsigned long flags; |
|---|
| 1982 | 2423 | long remaining; |
|---|
| 1983 | 2424 | #if MALI_USE_CSF |
|---|
| 1984 | | - long timeout = kbase_csf_timeout_in_jiffies(PM_TIMEOUT_MS); |
|---|
| 2425 | + long timeout = kbase_csf_timeout_in_jiffies(kbase_get_timeout_ms(kbdev, CSF_PM_TIMEOUT)); |
|---|
| 1985 | 2426 | #else |
|---|
| 1986 | 2427 | long timeout = msecs_to_jiffies(PM_TIMEOUT_MS); |
|---|
| 1987 | 2428 | #endif |
|---|
| .. | .. |
|---|
| 2015 | 2456 | return err; |
|---|
| 2016 | 2457 | } |
|---|
| 2017 | 2458 | KBASE_EXPORT_TEST_API(kbase_pm_wait_for_desired_state); |
|---|
| 2459 | + |
|---|
| 2460 | +#if MALI_USE_CSF |
|---|
| 2461 | +/** |
|---|
| 2462 | + * core_mask_update_done - Check if downscaling of shader cores is done |
|---|
| 2463 | + * |
|---|
| 2464 | + * @kbdev: The kbase device structure for the device. |
|---|
| 2465 | + * |
|---|
| 2466 | + * This function checks if the downscaling of cores is effectively complete. |
|---|
| 2467 | + * |
|---|
| 2468 | + * Return: true if the downscale is done. |
|---|
| 2469 | + */ |
|---|
| 2470 | +static bool core_mask_update_done(struct kbase_device *kbdev) |
|---|
| 2471 | +{ |
|---|
| 2472 | + bool update_done = false; |
|---|
| 2473 | + unsigned long flags; |
|---|
| 2474 | + |
|---|
| 2475 | + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); |
|---|
| 2476 | + /* If MCU is in stable ON state then it implies that the downscale |
|---|
| 2477 | + * request had completed. |
|---|
| 2478 | + * If MCU is not active then it implies all cores are off, so can |
|---|
| 2479 | + * consider the downscale request as complete. |
|---|
| 2480 | + */ |
|---|
| 2481 | + if ((kbdev->pm.backend.mcu_state == KBASE_MCU_ON) || |
|---|
| 2482 | + kbase_pm_is_mcu_inactive(kbdev, kbdev->pm.backend.mcu_state)) |
|---|
| 2483 | + update_done = true; |
|---|
| 2484 | + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); |
|---|
| 2485 | + |
|---|
| 2486 | + return update_done; |
|---|
| 2487 | +} |
|---|
| 2488 | + |
|---|
| 2489 | +int kbase_pm_wait_for_cores_down_scale(struct kbase_device *kbdev) |
|---|
| 2490 | +{ |
|---|
| 2491 | + long timeout = kbase_csf_timeout_in_jiffies(kbase_get_timeout_ms(kbdev, CSF_PM_TIMEOUT)); |
|---|
| 2492 | + long remaining; |
|---|
| 2493 | + int err = 0; |
|---|
| 2494 | + |
|---|
| 2495 | + /* Wait for core mask update to complete */ |
|---|
| 2496 | +#if KERNEL_VERSION(4, 13, 1) <= LINUX_VERSION_CODE |
|---|
| 2497 | + remaining = wait_event_killable_timeout( |
|---|
| 2498 | + kbdev->pm.backend.gpu_in_desired_state_wait, |
|---|
| 2499 | + core_mask_update_done(kbdev), timeout); |
|---|
| 2500 | +#else |
|---|
| 2501 | + remaining = wait_event_timeout( |
|---|
| 2502 | + kbdev->pm.backend.gpu_in_desired_state_wait, |
|---|
| 2503 | + core_mask_update_done(kbdev), timeout); |
|---|
| 2504 | +#endif |
|---|
| 2505 | + |
|---|
| 2506 | + if (!remaining) { |
|---|
| 2507 | + kbase_pm_timed_out(kbdev); |
|---|
| 2508 | + err = -ETIMEDOUT; |
|---|
| 2509 | + } else if (remaining < 0) { |
|---|
| 2510 | + dev_info( |
|---|
| 2511 | + kbdev->dev, |
|---|
| 2512 | + "Wait for cores down scaling got interrupted"); |
|---|
| 2513 | + err = (int)remaining; |
|---|
| 2514 | + } |
|---|
| 2515 | + |
|---|
| 2516 | + return err; |
|---|
| 2517 | +} |
|---|
| 2518 | +#endif |
|---|
| 2018 | 2519 | |
|---|
| 2019 | 2520 | void kbase_pm_enable_interrupts(struct kbase_device *kbdev) |
|---|
| 2020 | 2521 | { |
|---|
| .. | .. |
|---|
| 2074 | 2575 | KBASE_EXPORT_TEST_API(kbase_pm_disable_interrupts); |
|---|
| 2075 | 2576 | |
|---|
| 2076 | 2577 | #if MALI_USE_CSF |
|---|
| 2578 | +/** |
|---|
| 2579 | + * update_user_reg_page_mapping - Update the mapping for USER Register page |
|---|
| 2580 | + * |
|---|
| 2581 | + * @kbdev: The kbase device structure for the device. |
|---|
| 2582 | + * |
|---|
| 2583 | + * This function must be called to unmap the dummy or real page from USER Register page |
|---|
| 2584 | + * mapping whenever GPU is powered up or down. The dummy or real page would get |
|---|
| 2585 | + * appropriately mapped in when Userspace reads the LATEST_FLUSH value. |
|---|
| 2586 | + */ |
|---|
| 2077 | 2587 | static void update_user_reg_page_mapping(struct kbase_device *kbdev) |
|---|
| 2078 | 2588 | { |
|---|
| 2589 | + struct kbase_context *kctx, *n; |
|---|
| 2590 | + |
|---|
| 2079 | 2591 | lockdep_assert_held(&kbdev->pm.lock); |
|---|
| 2080 | 2592 | |
|---|
| 2081 | | - if (kbdev->csf.mali_file_inode) { |
|---|
| 2082 | | - /* This would zap the pte corresponding to the mapping of User |
|---|
| 2083 | | - * register page for all the Kbase contexts. |
|---|
| 2593 | + mutex_lock(&kbdev->csf.reg_lock); |
|---|
| 2594 | + list_for_each_entry_safe(kctx, n, &kbdev->csf.user_reg.list, csf.user_reg.link) { |
|---|
| 2595 | + /* This would zap the PTE corresponding to the mapping of User |
|---|
| 2596 | + * Register page of the kbase context. The mapping will be reestablished |
|---|
| 2597 | + * when the context (user process) needs to access to the page. |
|---|
| 2084 | 2598 | */ |
|---|
| 2085 | | - unmap_mapping_range(kbdev->csf.mali_file_inode->i_mapping, |
|---|
| 2086 | | - BASEP_MEM_CSF_USER_REG_PAGE_HANDLE, |
|---|
| 2087 | | - PAGE_SIZE, 1); |
|---|
| 2599 | + unmap_mapping_range(kbdev->csf.user_reg.filp->f_inode->i_mapping, |
|---|
| 2600 | + kctx->csf.user_reg.file_offset << PAGE_SHIFT, PAGE_SIZE, 1); |
|---|
| 2601 | + list_del_init(&kctx->csf.user_reg.link); |
|---|
| 2602 | + dev_dbg(kbdev->dev, "Updated USER Reg page mapping of ctx %d_%d", kctx->tgid, |
|---|
| 2603 | + kctx->id); |
|---|
| 2088 | 2604 | } |
|---|
| 2605 | + mutex_unlock(&kbdev->csf.reg_lock); |
|---|
| 2089 | 2606 | } |
|---|
| 2090 | 2607 | #endif |
|---|
| 2091 | | - |
|---|
| 2092 | 2608 | |
|---|
| 2093 | 2609 | /* |
|---|
| 2094 | 2610 | * pmu layout: |
|---|
| .. | .. |
|---|
| 2098 | 2614 | */ |
|---|
| 2099 | 2615 | void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume) |
|---|
| 2100 | 2616 | { |
|---|
| 2617 | + struct kbase_pm_backend_data *backend = &kbdev->pm.backend; |
|---|
| 2101 | 2618 | bool reset_required = is_resume; |
|---|
| 2102 | 2619 | unsigned long flags; |
|---|
| 2103 | 2620 | |
|---|
| .. | .. |
|---|
| 2115 | 2632 | } |
|---|
| 2116 | 2633 | #endif |
|---|
| 2117 | 2634 | |
|---|
| 2118 | | - if (kbdev->pm.backend.gpu_powered) { |
|---|
| 2635 | + if (backend->gpu_powered) { |
|---|
| 2636 | +#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) |
|---|
| 2637 | + if (backend->gpu_idled) { |
|---|
| 2638 | + backend->callback_power_runtime_gpu_active(kbdev); |
|---|
| 2639 | + backend->gpu_idled = false; |
|---|
| 2640 | + } |
|---|
| 2641 | +#endif |
|---|
| 2119 | 2642 | /* Already turned on */ |
|---|
| 2120 | 2643 | if (kbdev->poweroff_pending) |
|---|
| 2121 | 2644 | kbase_pm_enable_interrupts(kbdev); |
|---|
| .. | .. |
|---|
| 2128 | 2651 | |
|---|
| 2129 | 2652 | KBASE_KTRACE_ADD(kbdev, PM_GPU_ON, NULL, 0u); |
|---|
| 2130 | 2653 | |
|---|
| 2131 | | - if (is_resume && kbdev->pm.backend.callback_power_resume) { |
|---|
| 2132 | | - kbdev->pm.backend.callback_power_resume(kbdev); |
|---|
| 2654 | + if (is_resume && backend->callback_power_resume) { |
|---|
| 2655 | + backend->callback_power_resume(kbdev); |
|---|
| 2133 | 2656 | return; |
|---|
| 2134 | | - } else if (kbdev->pm.backend.callback_power_on) { |
|---|
| 2135 | | - reset_required = kbdev->pm.backend.callback_power_on(kbdev); |
|---|
| 2657 | + } else if (backend->callback_power_on) { |
|---|
| 2658 | + reset_required = backend->callback_power_on(kbdev); |
|---|
| 2136 | 2659 | } |
|---|
| 2137 | 2660 | |
|---|
| 2138 | 2661 | spin_lock_irqsave(&kbdev->hwaccess_lock, flags); |
|---|
| 2139 | | - kbdev->pm.backend.gpu_powered = true; |
|---|
| 2662 | + backend->gpu_powered = true; |
|---|
| 2140 | 2663 | spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); |
|---|
| 2141 | 2664 | |
|---|
| 2142 | 2665 | #if MALI_USE_CSF |
|---|
| 2143 | 2666 | /* GPU has been turned on, can switch to actual register page */ |
|---|
| 2144 | 2667 | update_user_reg_page_mapping(kbdev); |
|---|
| 2145 | 2668 | #endif |
|---|
| 2669 | + |
|---|
| 2146 | 2670 | |
|---|
| 2147 | 2671 | if (reset_required) { |
|---|
| 2148 | 2672 | /* GPU state was lost, reset GPU to ensure it is in a |
|---|
| .. | .. |
|---|
| 2194 | 2718 | |
|---|
| 2195 | 2719 | /* Turn on the L2 caches */ |
|---|
| 2196 | 2720 | spin_lock_irqsave(&kbdev->hwaccess_lock, flags); |
|---|
| 2197 | | - kbdev->pm.backend.gpu_ready = true; |
|---|
| 2198 | | - kbdev->pm.backend.l2_desired = true; |
|---|
| 2721 | + backend->gpu_ready = true; |
|---|
| 2722 | + backend->l2_desired = true; |
|---|
| 2199 | 2723 | #if MALI_USE_CSF |
|---|
| 2200 | 2724 | if (reset_required) { |
|---|
| 2201 | 2725 | /* GPU reset was done after the power on, so send the post |
|---|
| .. | .. |
|---|
| 2209 | 2733 | #endif |
|---|
| 2210 | 2734 | kbase_pm_update_state(kbdev); |
|---|
| 2211 | 2735 | spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); |
|---|
| 2736 | + |
|---|
| 2737 | +#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) |
|---|
| 2738 | + /* GPU is now powered up. Invoke the GPU active callback as GPU idle |
|---|
| 2739 | + * callback would have been invoked before the power down. |
|---|
| 2740 | + */ |
|---|
| 2741 | + if (backend->gpu_idled) { |
|---|
| 2742 | + backend->callback_power_runtime_gpu_active(kbdev); |
|---|
| 2743 | + backend->gpu_idled = false; |
|---|
| 2744 | + } |
|---|
| 2745 | +#endif |
|---|
| 2212 | 2746 | } |
|---|
| 2213 | 2747 | |
|---|
| 2214 | 2748 | KBASE_EXPORT_TEST_API(kbase_pm_clock_on); |
|---|
| .. | .. |
|---|
| 2252 | 2786 | kbase_ipa_control_handle_gpu_power_off(kbdev); |
|---|
| 2253 | 2787 | #endif |
|---|
| 2254 | 2788 | |
|---|
| 2255 | | - kbdev->pm.backend.gpu_ready = false; |
|---|
| 2256 | | - |
|---|
| 2257 | | - /* The GPU power may be turned off from this point */ |
|---|
| 2258 | | - kbdev->pm.backend.gpu_powered = false; |
|---|
| 2259 | | - |
|---|
| 2789 | + if (kbase_is_gpu_removed(kbdev) |
|---|
| 2260 | 2790 | #ifdef CONFIG_MALI_ARBITER_SUPPORT |
|---|
| 2261 | | - if (kbase_pm_is_gpu_lost(kbdev)) { |
|---|
| 2791 | + || kbase_pm_is_gpu_lost(kbdev)) { |
|---|
| 2792 | +#else |
|---|
| 2793 | + ) { |
|---|
| 2794 | +#endif |
|---|
| 2262 | 2795 | /* Ensure we unblock any threads that are stuck waiting |
|---|
| 2263 | 2796 | * for the GPU |
|---|
| 2264 | 2797 | */ |
|---|
| 2265 | 2798 | kbase_gpu_cache_clean_wait_complete(kbdev); |
|---|
| 2266 | 2799 | } |
|---|
| 2267 | | -#endif |
|---|
| 2800 | + |
|---|
| 2801 | + kbdev->pm.backend.gpu_ready = false; |
|---|
| 2802 | + |
|---|
| 2803 | + /* The GPU power may be turned off from this point */ |
|---|
| 2804 | + kbdev->pm.backend.gpu_powered = false; |
|---|
| 2268 | 2805 | |
|---|
| 2269 | 2806 | spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); |
|---|
| 2270 | 2807 | |
|---|
| .. | .. |
|---|
| 2300 | 2837 | /** |
|---|
| 2301 | 2838 | * kbase_pm_wait_for_reset - Wait for a reset to happen |
|---|
| 2302 | 2839 | * |
|---|
| 2303 | | - * Wait for the %RESET_COMPLETED IRQ to occur, then reset the waiting state. |
|---|
| 2304 | | - * |
|---|
| 2305 | 2840 | * @kbdev: Kbase device |
|---|
| 2841 | + * |
|---|
| 2842 | + * Wait for the %RESET_COMPLETED IRQ to occur, then reset the waiting state. |
|---|
| 2306 | 2843 | */ |
|---|
| 2307 | 2844 | static void kbase_pm_wait_for_reset(struct kbase_device *kbdev) |
|---|
| 2308 | 2845 | { |
|---|
| .. | .. |
|---|
| 2431 | 2968 | { |
|---|
| 2432 | 2969 | struct device_node *np = kbdev->dev->of_node; |
|---|
| 2433 | 2970 | const u32 gpu_id = kbdev->gpu_props.props.raw_props.gpu_id; |
|---|
| 2434 | | - const u32 prod_id = (gpu_id & GPU_ID_VERSION_PRODUCT_ID) >> |
|---|
| 2435 | | - GPU_ID_VERSION_PRODUCT_ID_SHIFT; |
|---|
| 2971 | + const u32 prod_id = |
|---|
| 2972 | + (gpu_id & GPU_ID_VERSION_PRODUCT_ID) >> KBASE_GPU_ID_VERSION_PRODUCT_ID_SHIFT; |
|---|
| 2436 | 2973 | int error = 0; |
|---|
| 2437 | 2974 | |
|---|
| 2438 | 2975 | kbdev->hw_quirks_gpu = 0; |
|---|
| .. | .. |
|---|
| 2770 | 3307 | |
|---|
| 2771 | 3308 | /** |
|---|
| 2772 | 3309 | * kbase_pm_request_gpu_cycle_counter_do_request - Request cycle counters |
|---|
| 3310 | + * @kbdev: The kbase device structure of the device |
|---|
| 2773 | 3311 | * |
|---|
| 2774 | 3312 | * Increase the count of cycle counter users and turn the cycle counters on if |
|---|
| 2775 | 3313 | * they were previously off |
|---|
| .. | .. |
|---|
| 2780 | 3318 | * |
|---|
| 2781 | 3319 | * When this function is called the l2 cache must be on - i.e., the GPU must be |
|---|
| 2782 | 3320 | * on. |
|---|
| 2783 | | - * |
|---|
| 2784 | | - * @kbdev: The kbase device structure of the device |
|---|
| 2785 | 3321 | */ |
|---|
| 2786 | 3322 | static void |
|---|
| 2787 | 3323 | kbase_pm_request_gpu_cycle_counter_do_request(struct kbase_device *kbdev) |
|---|
| .. | .. |
|---|
| 2799 | 3335 | /* This might happen after GPU reset. |
|---|
| 2800 | 3336 | * Then counter needs to be kicked. |
|---|
| 2801 | 3337 | */ |
|---|
| 3338 | +#if !IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) |
|---|
| 2802 | 3339 | if (!(kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_STATUS)) & |
|---|
| 2803 | 3340 | GPU_STATUS_CYCLE_COUNT_ACTIVE)) { |
|---|
| 2804 | 3341 | kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), |
|---|
| 2805 | 3342 | GPU_COMMAND_CYCLE_COUNT_START); |
|---|
| 2806 | 3343 | } |
|---|
| 3344 | +#endif |
|---|
| 2807 | 3345 | } |
|---|
| 2808 | 3346 | |
|---|
| 2809 | 3347 | spin_unlock_irqrestore( |
|---|