| .. | .. |
|---|
| 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-2023 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 |
|---|
| .. | .. |
|---|
| 35 | 35 | #include <mali_kbase.h> |
|---|
| 36 | 36 | #include <mali_kbase_defs.h> |
|---|
| 37 | 37 | #include <mali_kbase_hwaccess_instr.h> |
|---|
| 38 | +#include <mali_kbase_hwaccess_time.h> |
|---|
| 38 | 39 | #include <mali_kbase_hw.h> |
|---|
| 39 | 40 | #include <mali_kbase_config_defaults.h> |
|---|
| 40 | 41 | #include <linux/priority_control_manager.h> |
|---|
| 41 | 42 | |
|---|
| 42 | 43 | #include <tl/mali_kbase_timeline.h> |
|---|
| 44 | +#include "mali_kbase_kinstr_prfcnt.h" |
|---|
| 43 | 45 | #include "mali_kbase_vinstr.h" |
|---|
| 44 | | -#include "mali_kbase_hwcnt_context.h" |
|---|
| 45 | | -#include "mali_kbase_hwcnt_virtualizer.h" |
|---|
| 46 | +#include "hwcnt/mali_kbase_hwcnt_context.h" |
|---|
| 47 | +#include "hwcnt/mali_kbase_hwcnt_virtualizer.h" |
|---|
| 46 | 48 | |
|---|
| 47 | 49 | #include "mali_kbase_device.h" |
|---|
| 48 | 50 | #include "mali_kbase_device_internal.h" |
|---|
| 49 | 51 | #include "backend/gpu/mali_kbase_pm_internal.h" |
|---|
| 50 | 52 | #include "backend/gpu/mali_kbase_irq_internal.h" |
|---|
| 51 | 53 | #include "mali_kbase_regs_history_debugfs.h" |
|---|
| 54 | +#include "mali_kbase_pbha.h" |
|---|
| 52 | 55 | |
|---|
| 53 | 56 | #ifdef CONFIG_MALI_ARBITER_SUPPORT |
|---|
| 54 | 57 | #include "arbiter/mali_kbase_arbiter_pm.h" |
|---|
| 55 | 58 | #endif /* CONFIG_MALI_ARBITER_SUPPORT */ |
|---|
| 56 | 59 | |
|---|
| 57 | | -/* NOTE: Magic - 0x45435254 (TRCE in ASCII). |
|---|
| 58 | | - * Supports tracing feature provided in the base module. |
|---|
| 59 | | - * Please keep it in sync with the value of base module. |
|---|
| 60 | | - */ |
|---|
| 61 | | -#define TRACE_BUFFER_HEADER_SPECIAL 0x45435254 |
|---|
| 60 | +#if defined(CONFIG_DEBUG_FS) && !IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) |
|---|
| 62 | 61 | |
|---|
| 63 | 62 | /* Number of register accesses for the buffer that we allocate during |
|---|
| 64 | 63 | * initialization time. The buffer size can be changed later via debugfs. |
|---|
| 65 | 64 | */ |
|---|
| 66 | 65 | #define KBASEP_DEFAULT_REGISTER_HISTORY_SIZE ((u16)512) |
|---|
| 66 | + |
|---|
| 67 | +#endif /* defined(CONFIG_DEBUG_FS) && !IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) */ |
|---|
| 67 | 68 | |
|---|
| 68 | 69 | static DEFINE_MUTEX(kbase_dev_list_lock); |
|---|
| 69 | 70 | static LIST_HEAD(kbase_dev_list); |
|---|
| .. | .. |
|---|
| 161 | 162 | /** |
|---|
| 162 | 163 | * mali_oom_notifier_handler - Mali driver out-of-memory handler |
|---|
| 163 | 164 | * |
|---|
| 164 | | - * @nb - notifier block - used to retrieve kbdev pointer |
|---|
| 165 | | - * @action - action (unused) |
|---|
| 166 | | - * @data - data pointer (unused) |
|---|
| 165 | + * @nb: notifier block - used to retrieve kbdev pointer |
|---|
| 166 | + * @action: action (unused) |
|---|
| 167 | + * @data: data pointer (unused) |
|---|
| 168 | + * |
|---|
| 167 | 169 | * This function simply lists memory usage by the Mali driver, per GPU device, |
|---|
| 168 | 170 | * for diagnostic purposes. |
|---|
| 171 | + * |
|---|
| 172 | + * Return: NOTIFY_OK on success, NOTIFY_BAD otherwise. |
|---|
| 169 | 173 | */ |
|---|
| 170 | 174 | static int mali_oom_notifier_handler(struct notifier_block *nb, |
|---|
| 171 | 175 | unsigned long action, void *data) |
|---|
| .. | .. |
|---|
| 187 | 191 | |
|---|
| 188 | 192 | mutex_lock(&kbdev->kctx_list_lock); |
|---|
| 189 | 193 | |
|---|
| 190 | | - list_for_each_entry (kctx, &kbdev->kctx_list, kctx_list_link) { |
|---|
| 194 | + list_for_each_entry(kctx, &kbdev->kctx_list, kctx_list_link) { |
|---|
| 191 | 195 | struct pid *pid_struct; |
|---|
| 192 | 196 | struct task_struct *task; |
|---|
| 197 | + struct pid *tgid_struct; |
|---|
| 198 | + struct task_struct *tgid_task; |
|---|
| 199 | + |
|---|
| 193 | 200 | unsigned long task_alloc_total = |
|---|
| 194 | 201 | KBASE_PAGES_TO_KIB(atomic_read(&(kctx->used_pages))); |
|---|
| 195 | 202 | |
|---|
| 196 | 203 | rcu_read_lock(); |
|---|
| 197 | 204 | pid_struct = find_get_pid(kctx->pid); |
|---|
| 198 | 205 | task = pid_task(pid_struct, PIDTYPE_PID); |
|---|
| 206 | + tgid_struct = find_get_pid(kctx->tgid); |
|---|
| 207 | + tgid_task = pid_task(tgid_struct, PIDTYPE_PID); |
|---|
| 199 | 208 | |
|---|
| 200 | 209 | dev_err(kbdev->dev, |
|---|
| 201 | | - "OOM notifier: tsk %s tgid (%u) pid (%u) %lu kB\n", |
|---|
| 202 | | - task ? task->comm : "[null task]", kctx->tgid, |
|---|
| 210 | + "OOM notifier: tsk %s:%s tgid (%u) pid (%u) %lu kB\n", |
|---|
| 211 | + tgid_task ? tgid_task->comm : "[null task]", |
|---|
| 212 | + task ? task->comm : "[null comm]", kctx->tgid, |
|---|
| 203 | 213 | kctx->pid, task_alloc_total); |
|---|
| 204 | 214 | |
|---|
| 205 | 215 | put_pid(pid_struct); |
|---|
| .. | .. |
|---|
| 273 | 283 | if (err) |
|---|
| 274 | 284 | goto dma_set_mask_failed; |
|---|
| 275 | 285 | |
|---|
| 286 | + |
|---|
| 287 | + /* There is no limit for Mali, so set to max. */ |
|---|
| 288 | + if (kbdev->dev->dma_parms) |
|---|
| 289 | + err = dma_set_max_seg_size(kbdev->dev, UINT_MAX); |
|---|
| 290 | + if (err) |
|---|
| 291 | + goto dma_set_mask_failed; |
|---|
| 292 | + |
|---|
| 276 | 293 | kbdev->nr_hw_address_spaces = kbdev->gpu_props.num_address_spaces; |
|---|
| 277 | 294 | |
|---|
| 278 | 295 | err = kbase_device_all_as_init(kbdev); |
|---|
| 279 | 296 | if (err) |
|---|
| 280 | 297 | goto dma_set_mask_failed; |
|---|
| 281 | 298 | |
|---|
| 282 | | - err = kbase_ktrace_init(kbdev); |
|---|
| 299 | + err = kbase_pbha_read_dtb(kbdev); |
|---|
| 283 | 300 | if (err) |
|---|
| 284 | 301 | goto term_as; |
|---|
| 285 | 302 | |
|---|
| .. | .. |
|---|
| 291 | 308 | |
|---|
| 292 | 309 | kbdev->pm.dvfs_period = DEFAULT_PM_DVFS_PERIOD; |
|---|
| 293 | 310 | |
|---|
| 294 | | - kbdev->reset_timeout_ms = DEFAULT_RESET_TIMEOUT_MS; |
|---|
| 311 | +#if MALI_USE_CSF |
|---|
| 312 | + kbdev->reset_timeout_ms = kbase_get_timeout_ms(kbdev, CSF_CSG_SUSPEND_TIMEOUT); |
|---|
| 313 | +#else |
|---|
| 314 | + kbdev->reset_timeout_ms = JM_DEFAULT_RESET_TIMEOUT_MS; |
|---|
| 315 | +#endif /* MALI_USE_CSF */ |
|---|
| 295 | 316 | |
|---|
| 296 | 317 | kbdev->mmu_mode = kbase_mmu_mode_get_aarch64(); |
|---|
| 297 | | - |
|---|
| 318 | + kbdev->mmu_as_inactive_wait_time_ms = |
|---|
| 319 | + kbase_get_timeout_ms(kbdev, MMU_AS_INACTIVE_WAIT_TIMEOUT); |
|---|
| 298 | 320 | mutex_init(&kbdev->kctx_list_lock); |
|---|
| 299 | 321 | INIT_LIST_HEAD(&kbdev->kctx_list); |
|---|
| 300 | 322 | |
|---|
| .. | .. |
|---|
| 307 | 329 | "Unable to register OOM notifier for Mali - but will continue\n"); |
|---|
| 308 | 330 | kbdev->oom_notifier_block.notifier_call = NULL; |
|---|
| 309 | 331 | } |
|---|
| 332 | + |
|---|
| 333 | +#if !MALI_USE_CSF |
|---|
| 334 | + spin_lock_init(&kbdev->quick_reset_lock); |
|---|
| 335 | + kbdev->quick_reset_enabled = true; |
|---|
| 336 | + kbdev->num_of_atoms_hw_completed = 0; |
|---|
| 337 | +#endif |
|---|
| 338 | + |
|---|
| 339 | +#if MALI_USE_CSF && IS_ENABLED(CONFIG_SYNC_FILE) |
|---|
| 340 | + atomic_set(&kbdev->live_fence_metadata, 0); |
|---|
| 341 | +#endif |
|---|
| 310 | 342 | return 0; |
|---|
| 311 | 343 | |
|---|
| 312 | 344 | term_as: |
|---|
| .. | .. |
|---|
| 325 | 357 | #if KBASE_KTRACE_ENABLE |
|---|
| 326 | 358 | kbase_debug_assert_register_hook(NULL, NULL); |
|---|
| 327 | 359 | #endif |
|---|
| 328 | | - |
|---|
| 329 | | - kbase_ktrace_term(kbdev); |
|---|
| 330 | | - |
|---|
| 331 | 360 | kbase_device_all_as_term(kbdev); |
|---|
| 361 | + |
|---|
| 332 | 362 | |
|---|
| 333 | 363 | if (kbdev->oom_notifier_block.notifier_call) |
|---|
| 334 | 364 | unregister_oom_notifier(&kbdev->oom_notifier_block); |
|---|
| 365 | + |
|---|
| 366 | +#if MALI_USE_CSF && IS_ENABLED(CONFIG_SYNC_FILE) |
|---|
| 367 | + if (atomic_read(&kbdev->live_fence_metadata) > 0) |
|---|
| 368 | + dev_warn(kbdev->dev, "Terminating Kbase device with live fence metadata!"); |
|---|
| 369 | +#endif |
|---|
| 335 | 370 | } |
|---|
| 371 | + |
|---|
| 372 | +#if !MALI_USE_CSF |
|---|
| 373 | +void kbase_enable_quick_reset(struct kbase_device *kbdev) |
|---|
| 374 | +{ |
|---|
| 375 | + spin_lock(&kbdev->quick_reset_lock); |
|---|
| 376 | + |
|---|
| 377 | + kbdev->quick_reset_enabled = true; |
|---|
| 378 | + kbdev->num_of_atoms_hw_completed = 0; |
|---|
| 379 | + |
|---|
| 380 | + spin_unlock(&kbdev->quick_reset_lock); |
|---|
| 381 | +} |
|---|
| 382 | + |
|---|
| 383 | +void kbase_disable_quick_reset(struct kbase_device *kbdev) |
|---|
| 384 | +{ |
|---|
| 385 | + spin_lock(&kbdev->quick_reset_lock); |
|---|
| 386 | + |
|---|
| 387 | + kbdev->quick_reset_enabled = false; |
|---|
| 388 | + kbdev->num_of_atoms_hw_completed = 0; |
|---|
| 389 | + |
|---|
| 390 | + spin_unlock(&kbdev->quick_reset_lock); |
|---|
| 391 | +} |
|---|
| 392 | + |
|---|
| 393 | +bool kbase_is_quick_reset_enabled(struct kbase_device *kbdev) |
|---|
| 394 | +{ |
|---|
| 395 | + return kbdev->quick_reset_enabled; |
|---|
| 396 | +} |
|---|
| 397 | +#endif |
|---|
| 336 | 398 | |
|---|
| 337 | 399 | void kbase_device_free(struct kbase_device *kbdev) |
|---|
| 338 | 400 | { |
|---|
| .. | .. |
|---|
| 395 | 457 | kbase_vinstr_term(kbdev->vinstr_ctx); |
|---|
| 396 | 458 | } |
|---|
| 397 | 459 | |
|---|
| 398 | | -#if defined(CONFIG_DEBUG_FS) && !IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) |
|---|
| 460 | +int kbase_device_kinstr_prfcnt_init(struct kbase_device *kbdev) |
|---|
| 461 | +{ |
|---|
| 462 | + return kbase_kinstr_prfcnt_init(kbdev->hwcnt_gpu_virt, |
|---|
| 463 | + &kbdev->kinstr_prfcnt_ctx); |
|---|
| 464 | +} |
|---|
| 465 | + |
|---|
| 466 | +void kbase_device_kinstr_prfcnt_term(struct kbase_device *kbdev) |
|---|
| 467 | +{ |
|---|
| 468 | + kbase_kinstr_prfcnt_term(kbdev->kinstr_prfcnt_ctx); |
|---|
| 469 | +} |
|---|
| 470 | + |
|---|
| 399 | 471 | int kbase_device_io_history_init(struct kbase_device *kbdev) |
|---|
| 400 | 472 | { |
|---|
| 401 | 473 | return kbase_io_history_init(&kbdev->io_history, |
|---|
| .. | .. |
|---|
| 406 | 478 | { |
|---|
| 407 | 479 | kbase_io_history_term(&kbdev->io_history); |
|---|
| 408 | 480 | } |
|---|
| 409 | | -#endif |
|---|
| 410 | 481 | |
|---|
| 411 | 482 | int kbase_device_misc_register(struct kbase_device *kbdev) |
|---|
| 412 | 483 | { |
|---|
| .. | .. |
|---|
| 455 | 526 | { |
|---|
| 456 | 527 | int err; |
|---|
| 457 | 528 | |
|---|
| 458 | | - err = kbasep_platform_device_init(kbdev); |
|---|
| 529 | + err = kbase_ktrace_init(kbdev); |
|---|
| 459 | 530 | if (err) |
|---|
| 460 | 531 | return err; |
|---|
| 532 | + |
|---|
| 533 | + |
|---|
| 534 | + err = kbasep_platform_device_init(kbdev); |
|---|
| 535 | + if (err) |
|---|
| 536 | + goto ktrace_term; |
|---|
| 461 | 537 | |
|---|
| 462 | 538 | err = kbase_pm_runtime_init(kbdev); |
|---|
| 463 | 539 | if (err) |
|---|
| 464 | 540 | goto fail_runtime_pm; |
|---|
| 465 | 541 | |
|---|
| 542 | + /* This spinlock is initialized before doing the first access to GPU |
|---|
| 543 | + * registers and installing interrupt handlers. |
|---|
| 544 | + */ |
|---|
| 545 | + spin_lock_init(&kbdev->hwaccess_lock); |
|---|
| 546 | + |
|---|
| 466 | 547 | /* Ensure we can access the GPU registers */ |
|---|
| 467 | 548 | kbase_pm_register_access_enable(kbdev); |
|---|
| 468 | 549 | |
|---|
| 469 | | - /* Find out GPU properties based on the GPU feature registers */ |
|---|
| 550 | + /* |
|---|
| 551 | + * Find out GPU properties based on the GPU feature registers. |
|---|
| 552 | + * Note that this does not populate the few properties that depend on |
|---|
| 553 | + * hw_features being initialized. Those are set by kbase_gpuprops_set_features |
|---|
| 554 | + * soon after this in the init process. |
|---|
| 555 | + */ |
|---|
| 470 | 556 | kbase_gpuprops_set(kbdev); |
|---|
| 471 | 557 | |
|---|
| 472 | 558 | /* We're done accessing the GPU registers for now. */ |
|---|
| 473 | 559 | kbase_pm_register_access_disable(kbdev); |
|---|
| 474 | 560 | |
|---|
| 475 | | - /* This spinlock has to be initialized before installing interrupt |
|---|
| 476 | | - * handlers that require to hold it to process interrupts. |
|---|
| 477 | | - */ |
|---|
| 478 | | - spin_lock_init(&kbdev->hwaccess_lock); |
|---|
| 479 | 561 | #ifdef CONFIG_MALI_ARBITER_SUPPORT |
|---|
| 480 | 562 | if (kbdev->arb.arb_if) |
|---|
| 481 | 563 | err = kbase_arbiter_pm_install_interrupts(kbdev); |
|---|
| .. | .. |
|---|
| 493 | 575 | kbase_pm_runtime_term(kbdev); |
|---|
| 494 | 576 | fail_runtime_pm: |
|---|
| 495 | 577 | kbasep_platform_device_term(kbdev); |
|---|
| 578 | +ktrace_term: |
|---|
| 579 | + kbase_ktrace_term(kbdev); |
|---|
| 496 | 580 | |
|---|
| 497 | 581 | return err; |
|---|
| 498 | 582 | } |
|---|
| .. | .. |
|---|
| 509 | 593 | #endif /* CONFIG_MALI_ARBITER_SUPPORT */ |
|---|
| 510 | 594 | kbase_pm_runtime_term(kbdev); |
|---|
| 511 | 595 | kbasep_platform_device_term(kbdev); |
|---|
| 596 | + kbase_ktrace_term(kbdev); |
|---|
| 512 | 597 | } |
|---|
| 513 | 598 | |
|---|
| 514 | 599 | int kbase_device_late_init(struct kbase_device *kbdev) |
|---|