.. | .. |
---|
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 |
---|
.. | .. |
---|
33 | 33 | #include <mali_kbase_reset_gpu.h> |
---|
34 | 34 | #include <mali_kbase_ctx_sched.h> |
---|
35 | 35 | #include <mali_kbase_kinstr_jm.h> |
---|
36 | | -#include <mali_kbase_hwcnt_context.h> |
---|
| 36 | +#include <mali_kbase_hwaccess_instr.h> |
---|
| 37 | +#include <hwcnt/mali_kbase_hwcnt_context.h> |
---|
37 | 38 | #include <device/mali_kbase_device.h> |
---|
38 | 39 | #include <backend/gpu/mali_kbase_irq_internal.h> |
---|
39 | 40 | #include <backend/gpu/mali_kbase_jm_internal.h> |
---|
.. | .. |
---|
43 | 44 | static u64 kbasep_apply_limited_core_mask(const struct kbase_device *kbdev, |
---|
44 | 45 | const u64 affinity, const u64 limited_core_mask); |
---|
45 | 46 | |
---|
46 | | -static u64 kbase_job_write_affinity(struct kbase_device *kbdev, |
---|
47 | | - base_jd_core_req core_req, |
---|
48 | | - int js, const u64 limited_core_mask) |
---|
| 47 | +static u64 kbase_job_write_affinity(struct kbase_device *kbdev, base_jd_core_req core_req, |
---|
| 48 | + unsigned int js, const u64 limited_core_mask) |
---|
49 | 49 | { |
---|
50 | 50 | u64 affinity; |
---|
| 51 | + bool skip_affinity_check = false; |
---|
51 | 52 | |
---|
52 | 53 | if ((core_req & (BASE_JD_REQ_FS | BASE_JD_REQ_CS | BASE_JD_REQ_T)) == |
---|
53 | 54 | BASE_JD_REQ_T) { |
---|
54 | | - /* Tiler-only atom */ |
---|
55 | | - /* If the hardware supports XAFFINITY then we'll only enable |
---|
56 | | - * the tiler (which is the default so this is a no-op), |
---|
57 | | - * otherwise enable shader core 0. |
---|
58 | | - */ |
---|
59 | | - if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_XAFFINITY)) |
---|
60 | | - affinity = 1; |
---|
61 | | - else |
---|
62 | | - affinity = 0; |
---|
| 55 | + /* Tiler-only atom, affinity value can be programed as 0 */ |
---|
| 56 | + affinity = 0; |
---|
| 57 | + skip_affinity_check = true; |
---|
63 | 58 | } else if ((core_req & (BASE_JD_REQ_COHERENT_GROUP | |
---|
64 | 59 | BASE_JD_REQ_SPECIFIC_COHERENT_GROUP))) { |
---|
65 | 60 | unsigned int num_core_groups = kbdev->gpu_props.num_core_groups; |
---|
.. | .. |
---|
89 | 84 | affinity = kbasep_apply_limited_core_mask(kbdev, affinity, limited_core_mask); |
---|
90 | 85 | } |
---|
91 | 86 | |
---|
92 | | - if (unlikely(!affinity)) { |
---|
| 87 | + if (unlikely(!affinity && !skip_affinity_check)) { |
---|
93 | 88 | #ifdef CONFIG_MALI_BIFROST_DEBUG |
---|
94 | 89 | u64 shaders_ready = |
---|
95 | 90 | kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER); |
---|
.. | .. |
---|
195 | 190 | return jc; |
---|
196 | 191 | } |
---|
197 | 192 | |
---|
198 | | -void kbase_job_hw_submit(struct kbase_device *kbdev, |
---|
199 | | - struct kbase_jd_atom *katom, |
---|
200 | | - int js) |
---|
| 193 | +static inline bool kbasep_jm_wait_js_free(struct kbase_device *kbdev, unsigned int js, |
---|
| 194 | + struct kbase_context *kctx) |
---|
| 195 | +{ |
---|
| 196 | + const ktime_t wait_loop_start = ktime_get_raw(); |
---|
| 197 | + const s64 max_timeout = (s64)kbdev->js_data.js_free_wait_time_ms; |
---|
| 198 | + s64 diff = 0; |
---|
| 199 | + |
---|
| 200 | + /* wait for the JS_COMMAND_NEXT register to reach the given status value */ |
---|
| 201 | + do { |
---|
| 202 | + if (!kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT))) |
---|
| 203 | + return true; |
---|
| 204 | + |
---|
| 205 | + diff = ktime_to_ms(ktime_sub(ktime_get_raw(), wait_loop_start)); |
---|
| 206 | + } while (diff < max_timeout); |
---|
| 207 | + |
---|
| 208 | + dev_err(kbdev->dev, "Timeout in waiting for job slot %u to become free for ctx %d_%u", js, |
---|
| 209 | + kctx->tgid, kctx->id); |
---|
| 210 | + |
---|
| 211 | + return false; |
---|
| 212 | +} |
---|
| 213 | + |
---|
| 214 | +int kbase_job_hw_submit(struct kbase_device *kbdev, struct kbase_jd_atom *katom, unsigned int js) |
---|
201 | 215 | { |
---|
202 | 216 | struct kbase_context *kctx; |
---|
203 | 217 | u32 cfg; |
---|
204 | 218 | u64 const jc_head = select_job_chain(katom); |
---|
205 | 219 | u64 affinity; |
---|
| 220 | + struct slot_rb *ptr_slot_rb = &kbdev->hwaccess.backend.slot_rb[js]; |
---|
206 | 221 | |
---|
207 | | - KBASE_DEBUG_ASSERT(kbdev); |
---|
208 | | - KBASE_DEBUG_ASSERT(katom); |
---|
| 222 | + lockdep_assert_held(&kbdev->hwaccess_lock); |
---|
209 | 223 | |
---|
210 | 224 | kctx = katom->kctx; |
---|
211 | 225 | |
---|
212 | 226 | /* Command register must be available */ |
---|
213 | | - KBASE_DEBUG_ASSERT(kbasep_jm_is_js_free(kbdev, js, kctx)); |
---|
| 227 | + if (!kbasep_jm_wait_js_free(kbdev, js, kctx)) |
---|
| 228 | + return -EPERM; |
---|
214 | 229 | |
---|
215 | 230 | dev_dbg(kctx->kbdev->dev, "Write JS_HEAD_NEXT 0x%llx for atom %pK\n", |
---|
216 | 231 | jc_head, (void *)katom); |
---|
.. | .. |
---|
232 | 247 | !(kbdev->serialize_jobs & KBASE_SERIALIZE_RESET)) |
---|
233 | 248 | cfg |= JS_CONFIG_ENABLE_FLUSH_REDUCTION; |
---|
234 | 249 | |
---|
235 | | - if (0 != (katom->core_req & BASE_JD_REQ_SKIP_CACHE_START)) |
---|
236 | | - cfg |= JS_CONFIG_START_FLUSH_NO_ACTION; |
---|
237 | | - else |
---|
| 250 | + if (0 != (katom->core_req & BASE_JD_REQ_SKIP_CACHE_START)) { |
---|
| 251 | + /* Force a cache maintenance operation if the newly submitted |
---|
| 252 | + * katom to the slot is from a different kctx. For a JM GPU |
---|
| 253 | + * that has the feature BASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER, |
---|
| 254 | + * applies a FLUSH_INV_SHADER_OTHER. Otherwise, do a |
---|
| 255 | + * FLUSH_CLEAN_INVALIDATE. |
---|
| 256 | + */ |
---|
| 257 | + u64 tagged_kctx = ptr_slot_rb->last_kctx_tagged; |
---|
| 258 | + |
---|
| 259 | + if (tagged_kctx != SLOT_RB_NULL_TAG_VAL && tagged_kctx != SLOT_RB_TAG_KCTX(kctx)) { |
---|
| 260 | + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER)) |
---|
| 261 | + cfg |= JS_CONFIG_START_FLUSH_INV_SHADER_OTHER; |
---|
| 262 | + else |
---|
| 263 | + cfg |= JS_CONFIG_START_FLUSH_CLEAN_INVALIDATE; |
---|
| 264 | + } else |
---|
| 265 | + cfg |= JS_CONFIG_START_FLUSH_NO_ACTION; |
---|
| 266 | + } else |
---|
238 | 267 | cfg |= JS_CONFIG_START_FLUSH_CLEAN_INVALIDATE; |
---|
239 | 268 | |
---|
240 | 269 | if (0 != (katom->core_req & BASE_JD_REQ_SKIP_CACHE_END) && |
---|
.. | .. |
---|
251 | 280 | (katom->core_req & BASE_JD_REQ_END_RENDERPASS)) |
---|
252 | 281 | cfg |= JS_CONFIG_DISABLE_DESCRIPTOR_WR_BK; |
---|
253 | 282 | |
---|
254 | | - if (kbase_hw_has_feature(kbdev, |
---|
255 | | - BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION)) { |
---|
256 | | - if (!kbdev->hwaccess.backend.slot_rb[js].job_chain_flag) { |
---|
257 | | - cfg |= JS_CONFIG_JOB_CHAIN_FLAG; |
---|
258 | | - katom->atom_flags |= KBASE_KATOM_FLAGS_JOBCHAIN; |
---|
259 | | - kbdev->hwaccess.backend.slot_rb[js].job_chain_flag = |
---|
260 | | - true; |
---|
261 | | - } else { |
---|
262 | | - katom->atom_flags &= ~KBASE_KATOM_FLAGS_JOBCHAIN; |
---|
263 | | - kbdev->hwaccess.backend.slot_rb[js].job_chain_flag = |
---|
264 | | - false; |
---|
265 | | - } |
---|
| 283 | + if (!ptr_slot_rb->job_chain_flag) { |
---|
| 284 | + cfg |= JS_CONFIG_JOB_CHAIN_FLAG; |
---|
| 285 | + katom->atom_flags |= KBASE_KATOM_FLAGS_JOBCHAIN; |
---|
| 286 | + ptr_slot_rb->job_chain_flag = true; |
---|
| 287 | + } else { |
---|
| 288 | + katom->atom_flags &= ~KBASE_KATOM_FLAGS_JOBCHAIN; |
---|
| 289 | + ptr_slot_rb->job_chain_flag = false; |
---|
266 | 290 | } |
---|
267 | 291 | |
---|
268 | 292 | kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_CONFIG_NEXT), cfg); |
---|
.. | .. |
---|
274 | 298 | /* Write an approximate start timestamp. |
---|
275 | 299 | * It's approximate because there might be a job in the HEAD register. |
---|
276 | 300 | */ |
---|
277 | | - katom->start_timestamp = ktime_get(); |
---|
| 301 | + katom->start_timestamp = ktime_get_raw(); |
---|
278 | 302 | |
---|
279 | 303 | /* GO ! */ |
---|
280 | 304 | dev_dbg(kbdev->dev, "JS: Submitting atom %pK from ctx %pK to js[%d] with head=0x%llx", |
---|
.. | .. |
---|
300 | 324 | &kbdev->gpu_props.props.raw_props.js_features[js], |
---|
301 | 325 | "ctx_nr,atom_nr"); |
---|
302 | 326 | kbase_kinstr_jm_atom_hw_submit(katom); |
---|
| 327 | + |
---|
| 328 | + /* Update the slot's last katom submission kctx */ |
---|
| 329 | + ptr_slot_rb->last_kctx_tagged = SLOT_RB_TAG_KCTX(kctx); |
---|
| 330 | + |
---|
303 | 331 | #if IS_ENABLED(CONFIG_GPU_TRACEPOINTS) |
---|
304 | 332 | if (!kbase_backend_nr_atoms_submitted(kbdev, js)) { |
---|
305 | 333 | /* If this is the only job on the slot, trace it as starting */ |
---|
.. | .. |
---|
310 | 338 | sizeof(js_string)), |
---|
311 | 339 | ktime_to_ns(katom->start_timestamp), |
---|
312 | 340 | (u32)katom->kctx->id, 0, katom->work_id); |
---|
313 | | - kbdev->hwaccess.backend.slot_rb[js].last_context = katom->kctx; |
---|
314 | 341 | } |
---|
315 | 342 | #endif |
---|
316 | 343 | |
---|
.. | .. |
---|
319 | 346 | |
---|
320 | 347 | kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), |
---|
321 | 348 | JS_COMMAND_START); |
---|
| 349 | + |
---|
| 350 | + return 0; |
---|
322 | 351 | } |
---|
323 | 352 | |
---|
324 | 353 | /** |
---|
.. | .. |
---|
334 | 363 | * work out the best estimate (which might still result in an over-estimate to |
---|
335 | 364 | * the calculated time spent) |
---|
336 | 365 | */ |
---|
337 | | -static void kbasep_job_slot_update_head_start_timestamp( |
---|
338 | | - struct kbase_device *kbdev, |
---|
339 | | - int js, |
---|
340 | | - ktime_t end_timestamp) |
---|
| 366 | +static void kbasep_job_slot_update_head_start_timestamp(struct kbase_device *kbdev, unsigned int js, |
---|
| 367 | + ktime_t end_timestamp) |
---|
341 | 368 | { |
---|
342 | 369 | ktime_t timestamp_diff; |
---|
343 | 370 | struct kbase_jd_atom *katom; |
---|
.. | .. |
---|
367 | 394 | * Make a tracepoint call to the instrumentation module informing that |
---|
368 | 395 | * softstop happened on given lpu (job slot). |
---|
369 | 396 | */ |
---|
370 | | -static void kbasep_trace_tl_event_lpu_softstop(struct kbase_device *kbdev, |
---|
371 | | - int js) |
---|
| 397 | +static void kbasep_trace_tl_event_lpu_softstop(struct kbase_device *kbdev, unsigned int js) |
---|
372 | 398 | { |
---|
373 | 399 | KBASE_TLSTREAM_TL_EVENT_LPU_SOFTSTOP( |
---|
374 | 400 | kbdev, |
---|
.. | .. |
---|
377 | 403 | |
---|
378 | 404 | void kbase_job_done(struct kbase_device *kbdev, u32 done) |
---|
379 | 405 | { |
---|
380 | | - int i; |
---|
381 | 406 | u32 count = 0; |
---|
382 | 407 | ktime_t end_timestamp; |
---|
383 | 408 | |
---|
384 | 409 | lockdep_assert_held(&kbdev->hwaccess_lock); |
---|
385 | 410 | |
---|
386 | | - KBASE_DEBUG_ASSERT(kbdev); |
---|
387 | | - |
---|
388 | 411 | KBASE_KTRACE_ADD_JM(kbdev, JM_IRQ, NULL, NULL, 0, done); |
---|
389 | 412 | |
---|
390 | | - end_timestamp = ktime_get(); |
---|
| 413 | + end_timestamp = ktime_get_raw(); |
---|
391 | 414 | |
---|
392 | 415 | while (done) { |
---|
| 416 | + unsigned int i; |
---|
393 | 417 | u32 failed = done >> 16; |
---|
394 | 418 | |
---|
395 | 419 | /* treat failed slots as finished slots */ |
---|
.. | .. |
---|
399 | 423 | * numbered interrupts before the higher numbered ones. |
---|
400 | 424 | */ |
---|
401 | 425 | i = ffs(finished) - 1; |
---|
402 | | - KBASE_DEBUG_ASSERT(i >= 0); |
---|
403 | 426 | |
---|
404 | 427 | do { |
---|
405 | 428 | int nr_done; |
---|
.. | .. |
---|
415 | 438 | JOB_SLOT_REG(i, JS_STATUS)); |
---|
416 | 439 | |
---|
417 | 440 | if (completion_code == BASE_JD_EVENT_STOPPED) { |
---|
| 441 | + u64 job_head; |
---|
| 442 | + |
---|
418 | 443 | KBASE_TLSTREAM_AUX_EVENT_JOB_SLOT( |
---|
419 | 444 | kbdev, NULL, |
---|
420 | 445 | i, 0, TL_JS_EVENT_SOFT_STOP); |
---|
.. | .. |
---|
431 | 456 | ((u64)kbase_reg_read(kbdev, |
---|
432 | 457 | JOB_SLOT_REG(i, JS_TAIL_HI)) |
---|
433 | 458 | << 32); |
---|
| 459 | + job_head = (u64)kbase_reg_read(kbdev, |
---|
| 460 | + JOB_SLOT_REG(i, JS_HEAD_LO)) | |
---|
| 461 | + ((u64)kbase_reg_read(kbdev, |
---|
| 462 | + JOB_SLOT_REG(i, JS_HEAD_HI)) |
---|
| 463 | + << 32); |
---|
| 464 | + /* For a soft-stopped job chain js_tail should |
---|
| 465 | + * same as the js_head, but if not then the |
---|
| 466 | + * job chain was incorrectly marked as |
---|
| 467 | + * soft-stopped. In such case we should not |
---|
| 468 | + * be resuming the job chain from js_tail and |
---|
| 469 | + * report the completion_code as UNKNOWN. |
---|
| 470 | + */ |
---|
| 471 | + if (job_tail != job_head) |
---|
| 472 | + completion_code = BASE_JD_EVENT_UNKNOWN; |
---|
| 473 | + |
---|
434 | 474 | } else if (completion_code == |
---|
435 | 475 | BASE_JD_EVENT_NOT_STARTED) { |
---|
436 | 476 | /* PRLAM-10673 can cause a TERMINATED |
---|
.. | .. |
---|
563 | 603 | failed = done >> 16; |
---|
564 | 604 | finished = (done & 0xFFFF) | failed; |
---|
565 | 605 | if (done) |
---|
566 | | - end_timestamp = ktime_get(); |
---|
| 606 | + end_timestamp = ktime_get_raw(); |
---|
567 | 607 | } while (finished & (1 << i)); |
---|
568 | 608 | |
---|
569 | 609 | kbasep_job_slot_update_head_start_timestamp(kbdev, i, |
---|
.. | .. |
---|
581 | 621 | KBASE_KTRACE_ADD_JM(kbdev, JM_IRQ_END, NULL, NULL, 0, count); |
---|
582 | 622 | } |
---|
583 | 623 | |
---|
584 | | -void kbasep_job_slot_soft_or_hard_stop_do_action(struct kbase_device *kbdev, |
---|
585 | | - int js, |
---|
586 | | - u32 action, |
---|
587 | | - base_jd_core_req core_reqs, |
---|
588 | | - struct kbase_jd_atom *target_katom) |
---|
| 624 | +void kbasep_job_slot_soft_or_hard_stop_do_action(struct kbase_device *kbdev, unsigned int js, |
---|
| 625 | + u32 action, base_jd_core_req core_reqs, |
---|
| 626 | + struct kbase_jd_atom *target_katom) |
---|
589 | 627 | { |
---|
590 | 628 | #if KBASE_KTRACE_ENABLE |
---|
591 | 629 | u32 status_reg_before; |
---|
592 | 630 | u64 job_in_head_before; |
---|
593 | 631 | u32 status_reg_after; |
---|
594 | 632 | |
---|
595 | | - KBASE_DEBUG_ASSERT(!(action & (~JS_COMMAND_MASK))); |
---|
| 633 | + WARN_ON(action & (~JS_COMMAND_MASK)); |
---|
596 | 634 | |
---|
597 | 635 | /* Check the head pointer */ |
---|
598 | 636 | job_in_head_before = ((u64) kbase_reg_read(kbdev, |
---|
.. | .. |
---|
621 | 659 | /* Mark the point where we issue the soft-stop command */ |
---|
622 | 660 | KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTSTOP_ISSUE(kbdev, target_katom); |
---|
623 | 661 | |
---|
624 | | - if (kbase_hw_has_feature( |
---|
625 | | - kbdev, |
---|
626 | | - BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION)) { |
---|
627 | | - action = (target_katom->atom_flags & |
---|
628 | | - KBASE_KATOM_FLAGS_JOBCHAIN) ? |
---|
629 | | - JS_COMMAND_SOFT_STOP_1 : |
---|
630 | | - JS_COMMAND_SOFT_STOP_0; |
---|
631 | | - } |
---|
| 662 | + action = (target_katom->atom_flags & |
---|
| 663 | + KBASE_KATOM_FLAGS_JOBCHAIN) ? |
---|
| 664 | + JS_COMMAND_SOFT_STOP_1 : |
---|
| 665 | + JS_COMMAND_SOFT_STOP_0; |
---|
632 | 666 | } else if (action == JS_COMMAND_HARD_STOP) { |
---|
633 | 667 | target_katom->atom_flags |= KBASE_KATOM_FLAG_BEEN_HARD_STOPPED; |
---|
634 | 668 | |
---|
635 | | - if (kbase_hw_has_feature( |
---|
636 | | - kbdev, |
---|
637 | | - BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION)) { |
---|
638 | | - action = (target_katom->atom_flags & |
---|
639 | | - KBASE_KATOM_FLAGS_JOBCHAIN) ? |
---|
640 | | - JS_COMMAND_HARD_STOP_1 : |
---|
641 | | - JS_COMMAND_HARD_STOP_0; |
---|
642 | | - } |
---|
| 669 | + action = (target_katom->atom_flags & |
---|
| 670 | + KBASE_KATOM_FLAGS_JOBCHAIN) ? |
---|
| 671 | + JS_COMMAND_HARD_STOP_1 : |
---|
| 672 | + JS_COMMAND_HARD_STOP_0; |
---|
643 | 673 | } |
---|
644 | 674 | |
---|
645 | 675 | kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_COMMAND), action); |
---|
.. | .. |
---|
651 | 681 | struct kbase_context *head_kctx; |
---|
652 | 682 | |
---|
653 | 683 | head = kbase_gpu_inspect(kbdev, js, 0); |
---|
| 684 | + if (unlikely(!head)) { |
---|
| 685 | + dev_err(kbdev->dev, "Can't get a katom from js(%d)\n", js); |
---|
| 686 | + return; |
---|
| 687 | + } |
---|
654 | 688 | head_kctx = head->kctx; |
---|
655 | 689 | |
---|
656 | 690 | if (status_reg_before == BASE_JD_EVENT_ACTIVE) |
---|
.. | .. |
---|
678 | 712 | KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_HARDSTOP_1, head_kctx, head, head->jc, js); |
---|
679 | 713 | break; |
---|
680 | 714 | default: |
---|
681 | | - BUG(); |
---|
| 715 | + WARN(1, "Unknown action %d on atom %pK in kctx %pK\n", action, |
---|
| 716 | + (void *)target_katom, (void *)target_katom->kctx); |
---|
682 | 717 | break; |
---|
683 | 718 | } |
---|
684 | 719 | } else { |
---|
.. | .. |
---|
707 | 742 | KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_HARDSTOP_1, NULL, NULL, 0, js); |
---|
708 | 743 | break; |
---|
709 | 744 | default: |
---|
710 | | - BUG(); |
---|
| 745 | + WARN(1, "Unknown action %d on atom %pK in kctx %pK\n", action, |
---|
| 746 | + (void *)target_katom, (void *)target_katom->kctx); |
---|
711 | 747 | break; |
---|
712 | 748 | } |
---|
713 | 749 | } |
---|
.. | .. |
---|
717 | 753 | void kbase_backend_jm_kill_running_jobs_from_kctx(struct kbase_context *kctx) |
---|
718 | 754 | { |
---|
719 | 755 | struct kbase_device *kbdev = kctx->kbdev; |
---|
720 | | - int i; |
---|
| 756 | + unsigned int i; |
---|
721 | 757 | |
---|
722 | 758 | lockdep_assert_held(&kbdev->hwaccess_lock); |
---|
723 | 759 | |
---|
.. | .. |
---|
725 | 761 | kbase_job_slot_hardstop(kctx, i, NULL); |
---|
726 | 762 | } |
---|
727 | 763 | |
---|
728 | | -/** |
---|
729 | | - * kbase_is_existing_atom_submitted_later_than_ready |
---|
730 | | - * @ready: sequence number of the ready atom |
---|
731 | | - * @existing: sequence number of the existing atom |
---|
732 | | - * |
---|
733 | | - * Returns true if the existing atom has been submitted later than the |
---|
734 | | - * ready atom. It is used to understand if an atom that is ready has been |
---|
735 | | - * submitted earlier than the currently running atom, so that the currently |
---|
736 | | - * running atom should be preempted to allow the ready atom to run. |
---|
737 | | - */ |
---|
738 | | -static inline bool kbase_is_existing_atom_submitted_later_than_ready(u64 ready, u64 existing) |
---|
739 | | -{ |
---|
740 | | - /* No seq_nr set? */ |
---|
741 | | - if (!ready || !existing) |
---|
742 | | - return false; |
---|
743 | | - |
---|
744 | | - /* Efficiently handle the unlikely case of wrapping. |
---|
745 | | - * The following code assumes that the delta between the sequence number |
---|
746 | | - * of the two atoms is less than INT64_MAX. |
---|
747 | | - * In the extremely unlikely case where the delta is higher, the comparison |
---|
748 | | - * defaults for no preemption. |
---|
749 | | - * The code also assumes that the conversion from unsigned to signed types |
---|
750 | | - * works because the signed integers are 2's complement. |
---|
751 | | - */ |
---|
752 | | - return (s64)(ready - existing) < 0; |
---|
753 | | -} |
---|
754 | | - |
---|
755 | 764 | void kbase_job_slot_ctx_priority_check_locked(struct kbase_context *kctx, |
---|
756 | 765 | struct kbase_jd_atom *target_katom) |
---|
757 | 766 | { |
---|
758 | 767 | struct kbase_device *kbdev; |
---|
759 | | - int js = target_katom->slot_nr; |
---|
760 | | - int priority = target_katom->sched_priority; |
---|
761 | | - int seq_nr = target_katom->seq_nr; |
---|
| 768 | + unsigned int target_js = target_katom->slot_nr; |
---|
762 | 769 | int i; |
---|
763 | 770 | bool stop_sent = false; |
---|
764 | 771 | |
---|
765 | | - KBASE_DEBUG_ASSERT(kctx != NULL); |
---|
766 | 772 | kbdev = kctx->kbdev; |
---|
767 | | - KBASE_DEBUG_ASSERT(kbdev != NULL); |
---|
768 | 773 | |
---|
769 | 774 | lockdep_assert_held(&kbdev->hwaccess_lock); |
---|
770 | 775 | |
---|
771 | | - for (i = 0; i < kbase_backend_nr_atoms_on_slot(kbdev, js); i++) { |
---|
772 | | - struct kbase_jd_atom *katom; |
---|
| 776 | + for (i = 0; i < kbase_backend_nr_atoms_on_slot(kbdev, target_js); i++) { |
---|
| 777 | + struct kbase_jd_atom *slot_katom; |
---|
773 | 778 | |
---|
774 | | - katom = kbase_gpu_inspect(kbdev, js, i); |
---|
775 | | - if (!katom) |
---|
| 779 | + slot_katom = kbase_gpu_inspect(kbdev, target_js, i); |
---|
| 780 | + if (!slot_katom) |
---|
776 | 781 | continue; |
---|
777 | 782 | |
---|
778 | | - if ((kbdev->js_ctx_scheduling_mode == |
---|
779 | | - KBASE_JS_PROCESS_LOCAL_PRIORITY_MODE) && |
---|
780 | | - (katom->kctx != kctx)) |
---|
781 | | - continue; |
---|
782 | | - |
---|
783 | | - if ((katom->sched_priority > priority) || |
---|
784 | | - (katom->kctx == kctx && kbase_is_existing_atom_submitted_later_than_ready(seq_nr, katom->seq_nr))) { |
---|
| 783 | + if (kbase_js_atom_runs_before(kbdev, target_katom, slot_katom, |
---|
| 784 | + KBASE_ATOM_ORDERING_FLAG_SEQNR)) { |
---|
785 | 785 | if (!stop_sent) |
---|
786 | 786 | KBASE_TLSTREAM_TL_ATTRIB_ATOM_PRIORITIZED( |
---|
787 | 787 | kbdev, |
---|
788 | 788 | target_katom); |
---|
789 | 789 | |
---|
790 | | - kbase_job_slot_softstop(kbdev, js, katom); |
---|
| 790 | + kbase_job_slot_softstop(kbdev, target_js, slot_katom); |
---|
791 | 791 | stop_sent = true; |
---|
792 | 792 | } |
---|
793 | 793 | } |
---|
.. | .. |
---|
875 | 875 | if (timeout != 0) |
---|
876 | 876 | goto exit; |
---|
877 | 877 | |
---|
878 | | - if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE)) { |
---|
| 878 | + if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_HWC_UNRECOVERABLE_ERROR)) { |
---|
879 | 879 | dev_err(kbdev->dev, |
---|
880 | 880 | "Issuing GPU soft-reset because jobs failed to be killed (within %d ms) as part of context termination (e.g. process exit)\n", |
---|
881 | 881 | ZAP_TIMEOUT); |
---|
.. | .. |
---|
943 | 943 | * |
---|
944 | 944 | * Where possible any job in the next register is evicted before the soft-stop. |
---|
945 | 945 | */ |
---|
946 | | -void kbase_job_slot_softstop_swflags(struct kbase_device *kbdev, int js, |
---|
947 | | - struct kbase_jd_atom *target_katom, u32 sw_flags) |
---|
| 946 | +void kbase_job_slot_softstop_swflags(struct kbase_device *kbdev, unsigned int js, |
---|
| 947 | + struct kbase_jd_atom *target_katom, u32 sw_flags) |
---|
948 | 948 | { |
---|
949 | 949 | dev_dbg(kbdev->dev, "Soft-stop atom %pK with flags 0x%x (s:%d)\n", |
---|
950 | 950 | target_katom, sw_flags, js); |
---|
951 | 951 | |
---|
952 | | - KBASE_DEBUG_ASSERT(!(sw_flags & JS_COMMAND_MASK)); |
---|
| 952 | + if (sw_flags & JS_COMMAND_MASK) { |
---|
| 953 | + WARN(true, "Atom %pK in kctx %pK received non-NOP flags %d\n", (void *)target_katom, |
---|
| 954 | + target_katom ? (void *)target_katom->kctx : NULL, sw_flags); |
---|
| 955 | + sw_flags &= ~((u32)JS_COMMAND_MASK); |
---|
| 956 | + } |
---|
953 | 957 | kbase_backend_soft_hard_stop_slot(kbdev, NULL, js, target_katom, |
---|
954 | 958 | JS_COMMAND_SOFT_STOP | sw_flags); |
---|
955 | 959 | } |
---|
956 | 960 | |
---|
957 | | -/** |
---|
958 | | - * kbase_job_slot_softstop - Soft-stop the specified job slot |
---|
959 | | - * @kbdev: The kbase device |
---|
960 | | - * @js: The job slot to soft-stop |
---|
961 | | - * @target_katom: The job that should be soft-stopped (or NULL for any job) |
---|
962 | | - * Context: |
---|
963 | | - * The job slot lock must be held when calling this function. |
---|
964 | | - * The job slot must not already be in the process of being soft-stopped. |
---|
965 | | - * |
---|
966 | | - * Where possible any job in the next register is evicted before the soft-stop. |
---|
967 | | - */ |
---|
968 | 961 | void kbase_job_slot_softstop(struct kbase_device *kbdev, int js, |
---|
969 | 962 | struct kbase_jd_atom *target_katom) |
---|
970 | 963 | { |
---|
971 | 964 | kbase_job_slot_softstop_swflags(kbdev, js, target_katom, 0u); |
---|
972 | 965 | } |
---|
973 | 966 | |
---|
974 | | -/** |
---|
975 | | - * kbase_job_slot_hardstop - Hard-stop the specified job slot |
---|
976 | | - * @kctx: The kbase context that contains the job(s) that should |
---|
977 | | - * be hard-stopped |
---|
978 | | - * @js: The job slot to hard-stop |
---|
979 | | - * @target_katom: The job that should be hard-stopped (or NULL for all |
---|
980 | | - * jobs from the context) |
---|
981 | | - * Context: |
---|
982 | | - * The job slot lock must be held when calling this function. |
---|
983 | | - */ |
---|
984 | | -void kbase_job_slot_hardstop(struct kbase_context *kctx, int js, |
---|
985 | | - struct kbase_jd_atom *target_katom) |
---|
| 967 | +void kbase_job_slot_hardstop(struct kbase_context *kctx, unsigned int js, |
---|
| 968 | + struct kbase_jd_atom *target_katom) |
---|
986 | 969 | { |
---|
987 | 970 | struct kbase_device *kbdev = kctx->kbdev; |
---|
988 | 971 | bool stopped; |
---|
.. | .. |
---|
990 | 973 | stopped = kbase_backend_soft_hard_stop_slot(kbdev, kctx, js, |
---|
991 | 974 | target_katom, |
---|
992 | 975 | JS_COMMAND_HARD_STOP); |
---|
| 976 | + CSTD_UNUSED(stopped); |
---|
993 | 977 | } |
---|
994 | 978 | |
---|
995 | | -/** |
---|
996 | | - * kbase_job_check_enter_disjoint - potentiall enter disjoint mode |
---|
997 | | - * @kbdev: kbase device |
---|
998 | | - * @action: the event which has occurred |
---|
999 | | - * @core_reqs: core requirements of the atom |
---|
1000 | | - * @target_katom: the atom which is being affected |
---|
1001 | | - * |
---|
1002 | | - * For a certain soft-stop action, work out whether to enter disjoint |
---|
1003 | | - * state. |
---|
1004 | | - * |
---|
1005 | | - * This does not register multiple disjoint events if the atom has already |
---|
1006 | | - * started a disjoint period |
---|
1007 | | - * |
---|
1008 | | - * @core_reqs can be supplied as 0 if the atom had not started on the hardware |
---|
1009 | | - * (and so a 'real' soft/hard-stop was not required, but it still interrupted |
---|
1010 | | - * flow, perhaps on another context) |
---|
1011 | | - * |
---|
1012 | | - * kbase_job_check_leave_disjoint() should be used to end the disjoint |
---|
1013 | | - * state when the soft/hard-stop action is complete |
---|
1014 | | - */ |
---|
1015 | 979 | void kbase_job_check_enter_disjoint(struct kbase_device *kbdev, u32 action, |
---|
1016 | 980 | base_jd_core_req core_reqs, struct kbase_jd_atom *target_katom) |
---|
1017 | 981 | { |
---|
.. | .. |
---|
1033 | 997 | kbase_disjoint_state_up(kbdev); |
---|
1034 | 998 | } |
---|
1035 | 999 | |
---|
1036 | | -/** |
---|
1037 | | - * kbase_job_check_enter_disjoint - potentially leave disjoint state |
---|
1038 | | - * @kbdev: kbase device |
---|
1039 | | - * @target_katom: atom which is finishing |
---|
1040 | | - * |
---|
1041 | | - * Work out whether to leave disjoint state when finishing an atom that was |
---|
1042 | | - * originated by kbase_job_check_enter_disjoint(). |
---|
1043 | | - */ |
---|
1044 | 1000 | void kbase_job_check_leave_disjoint(struct kbase_device *kbdev, |
---|
1045 | 1001 | struct kbase_jd_atom *target_katom) |
---|
1046 | 1002 | { |
---|
.. | .. |
---|
1117 | 1073 | { |
---|
1118 | 1074 | unsigned long flags; |
---|
1119 | 1075 | struct kbase_device *kbdev; |
---|
1120 | | - ktime_t end_timestamp = ktime_get(); |
---|
| 1076 | + ktime_t end_timestamp = ktime_get_raw(); |
---|
1121 | 1077 | struct kbasep_js_device_data *js_devdata; |
---|
1122 | 1078 | bool silent = false; |
---|
1123 | 1079 | u32 max_loops = KBASE_CLEAN_CACHE_MAX_LOOPS; |
---|
1124 | 1080 | |
---|
1125 | | - KBASE_DEBUG_ASSERT(data); |
---|
1126 | | - |
---|
1127 | 1081 | kbdev = container_of(data, struct kbase_device, |
---|
1128 | 1082 | hwaccess.backend.reset_work); |
---|
1129 | 1083 | |
---|
1130 | | - KBASE_DEBUG_ASSERT(kbdev); |
---|
1131 | 1084 | js_devdata = &kbdev->js_data; |
---|
1132 | 1085 | |
---|
1133 | 1086 | if (atomic_read(&kbdev->hwaccess.backend.reset_gpu) == |
---|
1134 | 1087 | KBASE_RESET_GPU_SILENT) |
---|
| 1088 | + silent = true; |
---|
| 1089 | + |
---|
| 1090 | + if (kbase_is_quick_reset_enabled(kbdev)) |
---|
1135 | 1091 | silent = true; |
---|
1136 | 1092 | |
---|
1137 | 1093 | KBASE_KTRACE_ADD_JM(kbdev, JM_BEGIN_RESET_WORKER, NULL, NULL, 0u, 0); |
---|
.. | .. |
---|
1162 | 1118 | return; |
---|
1163 | 1119 | } |
---|
1164 | 1120 | |
---|
1165 | | - KBASE_DEBUG_ASSERT(kbdev->irq_reset_flush == false); |
---|
| 1121 | + WARN(kbdev->irq_reset_flush, "%s: GPU reset already in flight\n", __func__); |
---|
1166 | 1122 | |
---|
1167 | 1123 | spin_lock_irqsave(&kbdev->hwaccess_lock, flags); |
---|
1168 | 1124 | spin_lock(&kbdev->mmu_mask_change); |
---|
.. | .. |
---|
1203 | 1159 | |
---|
1204 | 1160 | mutex_lock(&kbdev->pm.lock); |
---|
1205 | 1161 | /* We hold the pm lock, so there ought to be a current policy */ |
---|
1206 | | - KBASE_DEBUG_ASSERT(kbdev->pm.backend.pm_current_policy); |
---|
| 1162 | + if (unlikely(!kbdev->pm.backend.pm_current_policy)) |
---|
| 1163 | + dev_warn(kbdev->dev, "No power policy set!"); |
---|
1207 | 1164 | |
---|
1208 | 1165 | /* All slot have been soft-stopped and we've waited |
---|
1209 | 1166 | * SOFT_STOP_RESET_TIMEOUT for the slots to clear, at this point we |
---|
.. | .. |
---|
1228 | 1185 | kbase_backend_reset(kbdev, &end_timestamp); |
---|
1229 | 1186 | kbase_pm_metrics_update(kbdev, NULL); |
---|
1230 | 1187 | spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); |
---|
| 1188 | + |
---|
| 1189 | + /* Tell hardware counters a reset is about to occur. |
---|
| 1190 | + * If the instr backend is in an unrecoverable error state (e.g. due to |
---|
| 1191 | + * HW being unresponsive), this will transition the backend out of |
---|
| 1192 | + * it, on the assumption a reset will fix whatever problem there was. |
---|
| 1193 | + */ |
---|
| 1194 | + kbase_instr_hwcnt_on_before_reset(kbdev); |
---|
1231 | 1195 | |
---|
1232 | 1196 | /* Reset the GPU */ |
---|
1233 | 1197 | kbase_pm_init_hw(kbdev, 0); |
---|
.. | .. |
---|
1293 | 1257 | struct kbase_device *kbdev = container_of(timer, struct kbase_device, |
---|
1294 | 1258 | hwaccess.backend.reset_timer); |
---|
1295 | 1259 | |
---|
1296 | | - KBASE_DEBUG_ASSERT(kbdev); |
---|
1297 | | - |
---|
1298 | 1260 | /* Reset still pending? */ |
---|
1299 | 1261 | if (atomic_cmpxchg(&kbdev->hwaccess.backend.reset_gpu, |
---|
1300 | 1262 | KBASE_RESET_GPU_COMMITTED, KBASE_RESET_GPU_HAPPENING) == |
---|
.. | .. |
---|
1312 | 1274 | |
---|
1313 | 1275 | static void kbasep_try_reset_gpu_early_locked(struct kbase_device *kbdev) |
---|
1314 | 1276 | { |
---|
1315 | | - int i; |
---|
| 1277 | + unsigned int i; |
---|
1316 | 1278 | int pending_jobs = 0; |
---|
1317 | | - |
---|
1318 | | - KBASE_DEBUG_ASSERT(kbdev); |
---|
1319 | 1279 | |
---|
1320 | 1280 | /* Count the number of jobs */ |
---|
1321 | 1281 | for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) |
---|
.. | .. |
---|
1361 | 1321 | * @kbdev: kbase device |
---|
1362 | 1322 | * @flags: Bitfield indicating impact of reset (see flag defines) |
---|
1363 | 1323 | * |
---|
1364 | | - * This function just soft-stops all the slots to ensure that as many jobs as |
---|
| 1324 | + * This function soft-stops all the slots to ensure that as many jobs as |
---|
1365 | 1325 | * possible are saved. |
---|
1366 | 1326 | * |
---|
1367 | | - * Return: |
---|
1368 | | - * The function returns a boolean which should be interpreted as follows: |
---|
| 1327 | + * Return: boolean which should be interpreted as follows: |
---|
1369 | 1328 | * true - Prepared for reset, kbase_reset_gpu_locked should be called. |
---|
1370 | 1329 | * false - Another thread is performing a reset, kbase_reset_gpu should |
---|
1371 | 1330 | * not be called. |
---|
.. | .. |
---|
1375 | 1334 | { |
---|
1376 | 1335 | int i; |
---|
1377 | 1336 | |
---|
1378 | | - CSTD_UNUSED(flags); |
---|
1379 | | - KBASE_DEBUG_ASSERT(kbdev); |
---|
1380 | | - |
---|
1381 | 1337 | #ifdef CONFIG_MALI_ARBITER_SUPPORT |
---|
1382 | 1338 | if (kbase_pm_is_gpu_lost(kbdev)) { |
---|
1383 | 1339 | /* GPU access has been removed, reset will be done by |
---|
.. | .. |
---|
1386 | 1342 | return false; |
---|
1387 | 1343 | } |
---|
1388 | 1344 | #endif |
---|
| 1345 | + |
---|
| 1346 | + if (flags & RESET_FLAGS_HWC_UNRECOVERABLE_ERROR) |
---|
| 1347 | + kbase_instr_hwcnt_on_unrecoverable_error(kbdev); |
---|
1389 | 1348 | |
---|
1390 | 1349 | if (atomic_cmpxchg(&kbdev->hwaccess.backend.reset_gpu, |
---|
1391 | 1350 | KBASE_RESET_GPU_NOT_PENDING, |
---|
.. | .. |
---|
1428 | 1387 | */ |
---|
1429 | 1388 | void kbase_reset_gpu(struct kbase_device *kbdev) |
---|
1430 | 1389 | { |
---|
1431 | | - KBASE_DEBUG_ASSERT(kbdev); |
---|
1432 | | - |
---|
1433 | 1390 | /* Note this is an assert/atomic_set because it is a software issue for |
---|
1434 | 1391 | * a race to be occurring here |
---|
1435 | 1392 | */ |
---|
1436 | | - KBASE_DEBUG_ASSERT(atomic_read(&kbdev->hwaccess.backend.reset_gpu) == |
---|
1437 | | - KBASE_RESET_GPU_PREPARED); |
---|
| 1393 | + if (WARN_ON(atomic_read(&kbdev->hwaccess.backend.reset_gpu) != KBASE_RESET_GPU_PREPARED)) |
---|
| 1394 | + return; |
---|
1438 | 1395 | atomic_set(&kbdev->hwaccess.backend.reset_gpu, |
---|
1439 | 1396 | KBASE_RESET_GPU_COMMITTED); |
---|
1440 | 1397 | |
---|
1441 | | - dev_err(kbdev->dev, "Preparing to soft-reset GPU: Waiting (upto %d ms) for all jobs to complete soft-stop\n", |
---|
1442 | | - kbdev->reset_timeout_ms); |
---|
| 1398 | + if (!kbase_is_quick_reset_enabled(kbdev)) |
---|
| 1399 | + dev_err(kbdev->dev, "Preparing to soft-reset GPU: Waiting (upto %d ms) for all jobs to complete soft-stop\n", |
---|
| 1400 | + kbdev->reset_timeout_ms); |
---|
1443 | 1401 | |
---|
1444 | 1402 | hrtimer_start(&kbdev->hwaccess.backend.reset_timer, |
---|
1445 | 1403 | HR_TIMER_DELAY_MSEC(kbdev->reset_timeout_ms), |
---|
.. | .. |
---|
1452 | 1410 | |
---|
1453 | 1411 | void kbase_reset_gpu_locked(struct kbase_device *kbdev) |
---|
1454 | 1412 | { |
---|
1455 | | - KBASE_DEBUG_ASSERT(kbdev); |
---|
1456 | | - |
---|
1457 | 1413 | /* Note this is an assert/atomic_set because it is a software issue for |
---|
1458 | 1414 | * a race to be occurring here |
---|
1459 | 1415 | */ |
---|
1460 | | - KBASE_DEBUG_ASSERT(atomic_read(&kbdev->hwaccess.backend.reset_gpu) == |
---|
1461 | | - KBASE_RESET_GPU_PREPARED); |
---|
| 1416 | + if (WARN_ON(atomic_read(&kbdev->hwaccess.backend.reset_gpu) != KBASE_RESET_GPU_PREPARED)) |
---|
| 1417 | + return; |
---|
1462 | 1418 | atomic_set(&kbdev->hwaccess.backend.reset_gpu, |
---|
1463 | 1419 | KBASE_RESET_GPU_COMMITTED); |
---|
1464 | 1420 | |
---|
1465 | | - dev_err(kbdev->dev, "Preparing to soft-reset GPU: Waiting (upto %d ms) for all jobs to complete soft-stop\n", |
---|
1466 | | - kbdev->reset_timeout_ms); |
---|
| 1421 | + if (!kbase_is_quick_reset_enabled(kbdev)) |
---|
| 1422 | + dev_err(kbdev->dev, "Preparing to soft-reset GPU: Waiting (upto %d ms) for all jobs to complete soft-stop\n", |
---|
| 1423 | + kbdev->reset_timeout_ms); |
---|
1467 | 1424 | hrtimer_start(&kbdev->hwaccess.backend.reset_timer, |
---|
1468 | 1425 | HR_TIMER_DELAY_MSEC(kbdev->reset_timeout_ms), |
---|
1469 | 1426 | HRTIMER_MODE_REL); |
---|
.. | .. |
---|
1497 | 1454 | return false; |
---|
1498 | 1455 | |
---|
1499 | 1456 | return true; |
---|
| 1457 | +} |
---|
| 1458 | + |
---|
| 1459 | +bool kbase_reset_gpu_is_not_pending(struct kbase_device *kbdev) |
---|
| 1460 | +{ |
---|
| 1461 | + return atomic_read(&kbdev->hwaccess.backend.reset_gpu) == KBASE_RESET_GPU_NOT_PENDING; |
---|
1500 | 1462 | } |
---|
1501 | 1463 | |
---|
1502 | 1464 | int kbase_reset_gpu_wait(struct kbase_device *kbdev) |
---|
.. | .. |
---|
1540 | 1502 | #ifdef CONFIG_MALI_BIFROST_DEBUG |
---|
1541 | 1503 | dev_dbg(kbdev->dev, |
---|
1542 | 1504 | "Limiting affinity due to BASE_JD_REQ_LIMITED_CORE_MASK from 0x%lx to 0x%lx (mask is 0x%lx)\n", |
---|
1543 | | - (unsigned long int)affinity, |
---|
1544 | | - (unsigned long int)result, |
---|
1545 | | - (unsigned long int)limited_core_mask); |
---|
| 1505 | + (unsigned long)affinity, |
---|
| 1506 | + (unsigned long)result, |
---|
| 1507 | + (unsigned long)limited_core_mask); |
---|
1546 | 1508 | #else |
---|
1547 | 1509 | CSTD_UNUSED(kbdev); |
---|
1548 | 1510 | #endif |
---|