1026 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2013 Red Hat4 * Author: Rob Clark <robdclark@gmail.com>5 */6 7#include "drm/drm_drv.h"8 9#include "msm_gpu.h"10#include "msm_gem.h"11#include "msm_mmu.h"12#include "msm_fence.h"13#include "msm_gpu_trace.h"14//#include "adreno/adreno_gpu.h"15 16#include <generated/utsrelease.h>17#include <linux/string_helpers.h>18#include <linux/devcoredump.h>19#include <linux/sched/task.h>20 21/*22 * Power Management:23 */24 25static int enable_pwrrail(struct msm_gpu *gpu)26{27 struct drm_device *dev = gpu->dev;28 int ret = 0;29 30 if (gpu->gpu_reg) {31 ret = regulator_enable(gpu->gpu_reg);32 if (ret) {33 DRM_DEV_ERROR(dev->dev, "failed to enable 'gpu_reg': %d\n", ret);34 return ret;35 }36 }37 38 if (gpu->gpu_cx) {39 ret = regulator_enable(gpu->gpu_cx);40 if (ret) {41 DRM_DEV_ERROR(dev->dev, "failed to enable 'gpu_cx': %d\n", ret);42 return ret;43 }44 }45 46 return 0;47}48 49static int disable_pwrrail(struct msm_gpu *gpu)50{51 if (gpu->gpu_cx)52 regulator_disable(gpu->gpu_cx);53 if (gpu->gpu_reg)54 regulator_disable(gpu->gpu_reg);55 return 0;56}57 58static int enable_clk(struct msm_gpu *gpu)59{60 if (gpu->core_clk && gpu->fast_rate)61 dev_pm_opp_set_rate(&gpu->pdev->dev, gpu->fast_rate);62 63 /* Set the RBBM timer rate to 19.2Mhz */64 if (gpu->rbbmtimer_clk)65 clk_set_rate(gpu->rbbmtimer_clk, 19200000);66 67 return clk_bulk_prepare_enable(gpu->nr_clocks, gpu->grp_clks);68}69 70static int disable_clk(struct msm_gpu *gpu)71{72 clk_bulk_disable_unprepare(gpu->nr_clocks, gpu->grp_clks);73 74 /*75 * Set the clock to a deliberately low rate. On older targets the clock76 * speed had to be non zero to avoid problems. On newer targets this77 * will be rounded down to zero anyway so it all works out.78 */79 if (gpu->core_clk)80 dev_pm_opp_set_rate(&gpu->pdev->dev, 27000000);81 82 if (gpu->rbbmtimer_clk)83 clk_set_rate(gpu->rbbmtimer_clk, 0);84 85 return 0;86}87 88static int enable_axi(struct msm_gpu *gpu)89{90 return clk_prepare_enable(gpu->ebi1_clk);91}92 93static int disable_axi(struct msm_gpu *gpu)94{95 clk_disable_unprepare(gpu->ebi1_clk);96 return 0;97}98 99int msm_gpu_pm_resume(struct msm_gpu *gpu)100{101 int ret;102 103 DBG("%s", gpu->name);104 trace_msm_gpu_resume(0);105 106 ret = enable_pwrrail(gpu);107 if (ret)108 return ret;109 110 ret = enable_clk(gpu);111 if (ret)112 return ret;113 114 ret = enable_axi(gpu);115 if (ret)116 return ret;117 118 msm_devfreq_resume(gpu);119 120 gpu->needs_hw_init = true;121 122 return 0;123}124 125int msm_gpu_pm_suspend(struct msm_gpu *gpu)126{127 int ret;128 129 DBG("%s", gpu->name);130 trace_msm_gpu_suspend(0);131 132 msm_devfreq_suspend(gpu);133 134 ret = disable_axi(gpu);135 if (ret)136 return ret;137 138 ret = disable_clk(gpu);139 if (ret)140 return ret;141 142 ret = disable_pwrrail(gpu);143 if (ret)144 return ret;145 146 gpu->suspend_count++;147 148 return 0;149}150 151void msm_gpu_show_fdinfo(struct msm_gpu *gpu, struct msm_file_private *ctx,152 struct drm_printer *p)153{154 drm_printf(p, "drm-engine-gpu:\t%llu ns\n", ctx->elapsed_ns);155 drm_printf(p, "drm-cycles-gpu:\t%llu\n", ctx->cycles);156 drm_printf(p, "drm-maxfreq-gpu:\t%u Hz\n", gpu->fast_rate);157}158 159int msm_gpu_hw_init(struct msm_gpu *gpu)160{161 int ret;162 163 WARN_ON(!mutex_is_locked(&gpu->lock));164 165 if (!gpu->needs_hw_init)166 return 0;167 168 disable_irq(gpu->irq);169 ret = gpu->funcs->hw_init(gpu);170 if (!ret)171 gpu->needs_hw_init = false;172 enable_irq(gpu->irq);173 174 return ret;175}176 177#ifdef CONFIG_DEV_COREDUMP178static ssize_t msm_gpu_devcoredump_read(char *buffer, loff_t offset,179 size_t count, void *data, size_t datalen)180{181 struct msm_gpu *gpu = data;182 struct drm_print_iterator iter;183 struct drm_printer p;184 struct msm_gpu_state *state;185 186 state = msm_gpu_crashstate_get(gpu);187 if (!state)188 return 0;189 190 iter.data = buffer;191 iter.offset = 0;192 iter.start = offset;193 iter.remain = count;194 195 p = drm_coredump_printer(&iter);196 197 drm_printf(&p, "---\n");198 drm_printf(&p, "kernel: " UTS_RELEASE "\n");199 drm_printf(&p, "module: " KBUILD_MODNAME "\n");200 drm_printf(&p, "time: %lld.%09ld\n",201 state->time.tv_sec, state->time.tv_nsec);202 if (state->comm)203 drm_printf(&p, "comm: %s\n", state->comm);204 if (state->cmd)205 drm_printf(&p, "cmdline: %s\n", state->cmd);206 207 gpu->funcs->show(gpu, state, &p);208 209 msm_gpu_crashstate_put(gpu);210 211 return count - iter.remain;212}213 214static void msm_gpu_devcoredump_free(void *data)215{216 struct msm_gpu *gpu = data;217 218 msm_gpu_crashstate_put(gpu);219}220 221static void msm_gpu_crashstate_get_bo(struct msm_gpu_state *state,222 struct drm_gem_object *obj, u64 iova, bool full)223{224 struct msm_gpu_state_bo *state_bo = &state->bos[state->nr_bos];225 struct msm_gem_object *msm_obj = to_msm_bo(obj);226 227 /* Don't record write only objects */228 state_bo->size = obj->size;229 state_bo->flags = msm_obj->flags;230 state_bo->iova = iova;231 232 BUILD_BUG_ON(sizeof(state_bo->name) != sizeof(msm_obj->name));233 234 memcpy(state_bo->name, msm_obj->name, sizeof(state_bo->name));235 236 if (full) {237 void *ptr;238 239 state_bo->data = kvmalloc(obj->size, GFP_KERNEL);240 if (!state_bo->data)241 goto out;242 243 msm_gem_lock(obj);244 ptr = msm_gem_get_vaddr_active(obj);245 msm_gem_unlock(obj);246 if (IS_ERR(ptr)) {247 kvfree(state_bo->data);248 state_bo->data = NULL;249 goto out;250 }251 252 memcpy(state_bo->data, ptr, obj->size);253 msm_gem_put_vaddr(obj);254 }255out:256 state->nr_bos++;257}258 259static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,260 struct msm_gem_submit *submit, char *comm, char *cmd)261{262 struct msm_gpu_state *state;263 264 /* Check if the target supports capturing crash state */265 if (!gpu->funcs->gpu_state_get)266 return;267 268 /* Only save one crash state at a time */269 if (gpu->crashstate)270 return;271 272 state = gpu->funcs->gpu_state_get(gpu);273 if (IS_ERR_OR_NULL(state))274 return;275 276 /* Fill in the additional crash state information */277 state->comm = kstrdup(comm, GFP_KERNEL);278 state->cmd = kstrdup(cmd, GFP_KERNEL);279 state->fault_info = gpu->fault_info;280 281 if (submit) {282 int i;283 284 state->bos = kcalloc(submit->nr_bos,285 sizeof(struct msm_gpu_state_bo), GFP_KERNEL);286 287 for (i = 0; state->bos && i < submit->nr_bos; i++) {288 msm_gpu_crashstate_get_bo(state, submit->bos[i].obj,289 submit->bos[i].iova,290 should_dump(submit, i));291 }292 }293 294 /* Set the active crash state to be dumped on failure */295 gpu->crashstate = state;296 297 dev_coredumpm(&gpu->pdev->dev, THIS_MODULE, gpu, 0, GFP_KERNEL,298 msm_gpu_devcoredump_read, msm_gpu_devcoredump_free);299}300#else301static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,302 struct msm_gem_submit *submit, char *comm, char *cmd)303{304}305#endif306 307/*308 * Hangcheck detection for locked gpu:309 */310 311static struct msm_gem_submit *312find_submit(struct msm_ringbuffer *ring, uint32_t fence)313{314 struct msm_gem_submit *submit;315 unsigned long flags;316 317 spin_lock_irqsave(&ring->submit_lock, flags);318 list_for_each_entry(submit, &ring->submits, node) {319 if (submit->seqno == fence) {320 spin_unlock_irqrestore(&ring->submit_lock, flags);321 return submit;322 }323 }324 spin_unlock_irqrestore(&ring->submit_lock, flags);325 326 return NULL;327}328 329static void retire_submits(struct msm_gpu *gpu);330 331static void get_comm_cmdline(struct msm_gem_submit *submit, char **comm, char **cmd)332{333 struct msm_file_private *ctx = submit->queue->ctx;334 struct task_struct *task;335 336 WARN_ON(!mutex_is_locked(&submit->gpu->lock));337 338 /* Note that kstrdup will return NULL if argument is NULL: */339 *comm = kstrdup(ctx->comm, GFP_KERNEL);340 *cmd = kstrdup(ctx->cmdline, GFP_KERNEL);341 342 task = get_pid_task(submit->pid, PIDTYPE_PID);343 if (!task)344 return;345 346 if (!*comm)347 *comm = kstrdup(task->comm, GFP_KERNEL);348 349 if (!*cmd)350 *cmd = kstrdup_quotable_cmdline(task, GFP_KERNEL);351 352 put_task_struct(task);353}354 355static void recover_worker(struct kthread_work *work)356{357 struct msm_gpu *gpu = container_of(work, struct msm_gpu, recover_work);358 struct drm_device *dev = gpu->dev;359 struct msm_drm_private *priv = dev->dev_private;360 struct msm_gem_submit *submit;361 struct msm_ringbuffer *cur_ring = gpu->funcs->active_ring(gpu);362 char *comm = NULL, *cmd = NULL;363 int i;364 365 mutex_lock(&gpu->lock);366 367 DRM_DEV_ERROR(dev->dev, "%s: hangcheck recover!\n", gpu->name);368 369 submit = find_submit(cur_ring, cur_ring->memptrs->fence + 1);370 371 /*372 * If the submit retired while we were waiting for the worker to run,373 * or waiting to acquire the gpu lock, then nothing more to do.374 */375 if (!submit)376 goto out_unlock;377 378 /* Increment the fault counts */379 submit->queue->faults++;380 if (submit->aspace)381 submit->aspace->faults++;382 383 get_comm_cmdline(submit, &comm, &cmd);384 385 if (comm && cmd) {386 DRM_DEV_ERROR(dev->dev, "%s: offending task: %s (%s)\n",387 gpu->name, comm, cmd);388 389 msm_rd_dump_submit(priv->hangrd, submit,390 "offending task: %s (%s)", comm, cmd);391 } else {392 DRM_DEV_ERROR(dev->dev, "%s: offending task: unknown\n", gpu->name);393 394 msm_rd_dump_submit(priv->hangrd, submit, NULL);395 }396 397 /* Record the crash state */398 pm_runtime_get_sync(&gpu->pdev->dev);399 msm_gpu_crashstate_capture(gpu, submit, comm, cmd);400 401 kfree(cmd);402 kfree(comm);403 404 /*405 * Update all the rings with the latest and greatest fence.. this406 * needs to happen after msm_rd_dump_submit() to ensure that the407 * bo's referenced by the offending submit are still around.408 */409 for (i = 0; i < gpu->nr_rings; i++) {410 struct msm_ringbuffer *ring = gpu->rb[i];411 412 uint32_t fence = ring->memptrs->fence;413 414 /*415 * For the current (faulting?) ring/submit advance the fence by416 * one more to clear the faulting submit417 */418 if (ring == cur_ring)419 ring->memptrs->fence = ++fence;420 421 msm_update_fence(ring->fctx, fence);422 }423 424 if (msm_gpu_active(gpu)) {425 /* retire completed submits, plus the one that hung: */426 retire_submits(gpu);427 428 gpu->funcs->recover(gpu);429 430 /*431 * Replay all remaining submits starting with highest priority432 * ring433 */434 for (i = 0; i < gpu->nr_rings; i++) {435 struct msm_ringbuffer *ring = gpu->rb[i];436 unsigned long flags;437 438 spin_lock_irqsave(&ring->submit_lock, flags);439 list_for_each_entry(submit, &ring->submits, node)440 gpu->funcs->submit(gpu, submit);441 spin_unlock_irqrestore(&ring->submit_lock, flags);442 }443 }444 445 pm_runtime_put(&gpu->pdev->dev);446 447out_unlock:448 mutex_unlock(&gpu->lock);449 450 msm_gpu_retire(gpu);451}452 453static void fault_worker(struct kthread_work *work)454{455 struct msm_gpu *gpu = container_of(work, struct msm_gpu, fault_work);456 struct msm_gem_submit *submit;457 struct msm_ringbuffer *cur_ring = gpu->funcs->active_ring(gpu);458 char *comm = NULL, *cmd = NULL;459 460 mutex_lock(&gpu->lock);461 462 submit = find_submit(cur_ring, cur_ring->memptrs->fence + 1);463 if (submit && submit->fault_dumped)464 goto resume_smmu;465 466 if (submit) {467 get_comm_cmdline(submit, &comm, &cmd);468 469 /*470 * When we get GPU iova faults, we can get 1000s of them,471 * but we really only want to log the first one.472 */473 submit->fault_dumped = true;474 }475 476 /* Record the crash state */477 pm_runtime_get_sync(&gpu->pdev->dev);478 msm_gpu_crashstate_capture(gpu, submit, comm, cmd);479 pm_runtime_put_sync(&gpu->pdev->dev);480 481 kfree(cmd);482 kfree(comm);483 484resume_smmu:485 memset(&gpu->fault_info, 0, sizeof(gpu->fault_info));486 gpu->aspace->mmu->funcs->resume_translation(gpu->aspace->mmu);487 488 mutex_unlock(&gpu->lock);489}490 491static void hangcheck_timer_reset(struct msm_gpu *gpu)492{493 struct msm_drm_private *priv = gpu->dev->dev_private;494 mod_timer(&gpu->hangcheck_timer,495 round_jiffies_up(jiffies + msecs_to_jiffies(priv->hangcheck_period)));496}497 498static bool made_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring)499{500 if (ring->hangcheck_progress_retries >= DRM_MSM_HANGCHECK_PROGRESS_RETRIES)501 return false;502 503 if (!gpu->funcs->progress)504 return false;505 506 if (!gpu->funcs->progress(gpu, ring))507 return false;508 509 ring->hangcheck_progress_retries++;510 return true;511}512 513static void hangcheck_handler(struct timer_list *t)514{515 struct msm_gpu *gpu = from_timer(gpu, t, hangcheck_timer);516 struct drm_device *dev = gpu->dev;517 struct msm_ringbuffer *ring = gpu->funcs->active_ring(gpu);518 uint32_t fence = ring->memptrs->fence;519 520 if (fence != ring->hangcheck_fence) {521 /* some progress has been made.. ya! */522 ring->hangcheck_fence = fence;523 ring->hangcheck_progress_retries = 0;524 } else if (fence_before(fence, ring->fctx->last_fence) &&525 !made_progress(gpu, ring)) {526 /* no progress and not done.. hung! */527 ring->hangcheck_fence = fence;528 ring->hangcheck_progress_retries = 0;529 DRM_DEV_ERROR(dev->dev, "%s: hangcheck detected gpu lockup rb %d!\n",530 gpu->name, ring->id);531 DRM_DEV_ERROR(dev->dev, "%s: completed fence: %u\n",532 gpu->name, fence);533 DRM_DEV_ERROR(dev->dev, "%s: submitted fence: %u\n",534 gpu->name, ring->fctx->last_fence);535 536 kthread_queue_work(gpu->worker, &gpu->recover_work);537 }538 539 /* if still more pending work, reset the hangcheck timer: */540 if (fence_after(ring->fctx->last_fence, ring->hangcheck_fence))541 hangcheck_timer_reset(gpu);542 543 /* workaround for missing irq: */544 msm_gpu_retire(gpu);545}546 547/*548 * Performance Counters:549 */550 551/* called under perf_lock */552static int update_hw_cntrs(struct msm_gpu *gpu, uint32_t ncntrs, uint32_t *cntrs)553{554 uint32_t current_cntrs[ARRAY_SIZE(gpu->last_cntrs)];555 int i, n = min(ncntrs, gpu->num_perfcntrs);556 557 /* read current values: */558 for (i = 0; i < gpu->num_perfcntrs; i++)559 current_cntrs[i] = gpu_read(gpu, gpu->perfcntrs[i].sample_reg);560 561 /* update cntrs: */562 for (i = 0; i < n; i++)563 cntrs[i] = current_cntrs[i] - gpu->last_cntrs[i];564 565 /* save current values: */566 for (i = 0; i < gpu->num_perfcntrs; i++)567 gpu->last_cntrs[i] = current_cntrs[i];568 569 return n;570}571 572static void update_sw_cntrs(struct msm_gpu *gpu)573{574 ktime_t time;575 uint32_t elapsed;576 unsigned long flags;577 578 spin_lock_irqsave(&gpu->perf_lock, flags);579 if (!gpu->perfcntr_active)580 goto out;581 582 time = ktime_get();583 elapsed = ktime_to_us(ktime_sub(time, gpu->last_sample.time));584 585 gpu->totaltime += elapsed;586 if (gpu->last_sample.active)587 gpu->activetime += elapsed;588 589 gpu->last_sample.active = msm_gpu_active(gpu);590 gpu->last_sample.time = time;591 592out:593 spin_unlock_irqrestore(&gpu->perf_lock, flags);594}595 596void msm_gpu_perfcntr_start(struct msm_gpu *gpu)597{598 unsigned long flags;599 600 pm_runtime_get_sync(&gpu->pdev->dev);601 602 spin_lock_irqsave(&gpu->perf_lock, flags);603 /* we could dynamically enable/disable perfcntr registers too.. */604 gpu->last_sample.active = msm_gpu_active(gpu);605 gpu->last_sample.time = ktime_get();606 gpu->activetime = gpu->totaltime = 0;607 gpu->perfcntr_active = true;608 update_hw_cntrs(gpu, 0, NULL);609 spin_unlock_irqrestore(&gpu->perf_lock, flags);610}611 612void msm_gpu_perfcntr_stop(struct msm_gpu *gpu)613{614 gpu->perfcntr_active = false;615 pm_runtime_put_sync(&gpu->pdev->dev);616}617 618/* returns -errno or # of cntrs sampled */619int msm_gpu_perfcntr_sample(struct msm_gpu *gpu, uint32_t *activetime,620 uint32_t *totaltime, uint32_t ncntrs, uint32_t *cntrs)621{622 unsigned long flags;623 int ret;624 625 spin_lock_irqsave(&gpu->perf_lock, flags);626 627 if (!gpu->perfcntr_active) {628 ret = -EINVAL;629 goto out;630 }631 632 *activetime = gpu->activetime;633 *totaltime = gpu->totaltime;634 635 gpu->activetime = gpu->totaltime = 0;636 637 ret = update_hw_cntrs(gpu, ncntrs, cntrs);638 639out:640 spin_unlock_irqrestore(&gpu->perf_lock, flags);641 642 return ret;643}644 645/*646 * Cmdstream submission/retirement:647 */648 649static void retire_submit(struct msm_gpu *gpu, struct msm_ringbuffer *ring,650 struct msm_gem_submit *submit)651{652 int index = submit->seqno % MSM_GPU_SUBMIT_STATS_COUNT;653 volatile struct msm_gpu_submit_stats *stats;654 u64 elapsed, clock = 0, cycles;655 unsigned long flags;656 657 stats = &ring->memptrs->stats[index];658 /* Convert 19.2Mhz alwayson ticks to nanoseconds for elapsed time */659 elapsed = (stats->alwayson_end - stats->alwayson_start) * 10000;660 do_div(elapsed, 192);661 662 cycles = stats->cpcycles_end - stats->cpcycles_start;663 664 /* Calculate the clock frequency from the number of CP cycles */665 if (elapsed) {666 clock = cycles * 1000;667 do_div(clock, elapsed);668 }669 670 submit->queue->ctx->elapsed_ns += elapsed;671 submit->queue->ctx->cycles += cycles;672 673 trace_msm_gpu_submit_retired(submit, elapsed, clock,674 stats->alwayson_start, stats->alwayson_end);675 676 msm_submit_retire(submit);677 678 pm_runtime_mark_last_busy(&gpu->pdev->dev);679 680 spin_lock_irqsave(&ring->submit_lock, flags);681 list_del(&submit->node);682 spin_unlock_irqrestore(&ring->submit_lock, flags);683 684 /* Update devfreq on transition from active->idle: */685 mutex_lock(&gpu->active_lock);686 gpu->active_submits--;687 WARN_ON(gpu->active_submits < 0);688 if (!gpu->active_submits) {689 msm_devfreq_idle(gpu);690 pm_runtime_put_autosuspend(&gpu->pdev->dev);691 }692 693 mutex_unlock(&gpu->active_lock);694 695 msm_gem_submit_put(submit);696}697 698static void retire_submits(struct msm_gpu *gpu)699{700 int i;701 702 /* Retire the commits starting with highest priority */703 for (i = 0; i < gpu->nr_rings; i++) {704 struct msm_ringbuffer *ring = gpu->rb[i];705 706 while (true) {707 struct msm_gem_submit *submit = NULL;708 unsigned long flags;709 710 spin_lock_irqsave(&ring->submit_lock, flags);711 submit = list_first_entry_or_null(&ring->submits,712 struct msm_gem_submit, node);713 spin_unlock_irqrestore(&ring->submit_lock, flags);714 715 /*716 * If no submit, we are done. If submit->fence hasn't717 * been signalled, then later submits are not signalled718 * either, so we are also done.719 */720 if (submit && dma_fence_is_signaled(submit->hw_fence)) {721 retire_submit(gpu, ring, submit);722 } else {723 break;724 }725 }726 }727 728 wake_up_all(&gpu->retire_event);729}730 731static void retire_worker(struct kthread_work *work)732{733 struct msm_gpu *gpu = container_of(work, struct msm_gpu, retire_work);734 735 retire_submits(gpu);736}737 738/* call from irq handler to schedule work to retire bo's */739void msm_gpu_retire(struct msm_gpu *gpu)740{741 int i;742 743 for (i = 0; i < gpu->nr_rings; i++)744 msm_update_fence(gpu->rb[i]->fctx, gpu->rb[i]->memptrs->fence);745 746 kthread_queue_work(gpu->worker, &gpu->retire_work);747 update_sw_cntrs(gpu);748}749 750/* add bo's to gpu's ring, and kick gpu: */751void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)752{753 struct msm_ringbuffer *ring = submit->ring;754 unsigned long flags;755 756 WARN_ON(!mutex_is_locked(&gpu->lock));757 758 pm_runtime_get_sync(&gpu->pdev->dev);759 760 msm_gpu_hw_init(gpu);761 762 submit->seqno = submit->hw_fence->seqno;763 764 update_sw_cntrs(gpu);765 766 /*767 * ring->submits holds a ref to the submit, to deal with the case768 * that a submit completes before msm_ioctl_gem_submit() returns.769 */770 msm_gem_submit_get(submit);771 772 spin_lock_irqsave(&ring->submit_lock, flags);773 list_add_tail(&submit->node, &ring->submits);774 spin_unlock_irqrestore(&ring->submit_lock, flags);775 776 /* Update devfreq on transition from idle->active: */777 mutex_lock(&gpu->active_lock);778 if (!gpu->active_submits) {779 pm_runtime_get(&gpu->pdev->dev);780 msm_devfreq_active(gpu);781 }782 gpu->active_submits++;783 mutex_unlock(&gpu->active_lock);784 785 gpu->funcs->submit(gpu, submit);786 gpu->cur_ctx_seqno = submit->queue->ctx->seqno;787 788 pm_runtime_put(&gpu->pdev->dev);789 hangcheck_timer_reset(gpu);790}791 792/*793 * Init/Cleanup:794 */795 796static irqreturn_t irq_handler(int irq, void *data)797{798 struct msm_gpu *gpu = data;799 return gpu->funcs->irq(gpu);800}801 802static int get_clocks(struct platform_device *pdev, struct msm_gpu *gpu)803{804 int ret = devm_clk_bulk_get_all(&pdev->dev, &gpu->grp_clks);805 806 if (ret < 1) {807 gpu->nr_clocks = 0;808 return ret;809 }810 811 gpu->nr_clocks = ret;812 813 gpu->core_clk = msm_clk_bulk_get_clock(gpu->grp_clks,814 gpu->nr_clocks, "core");815 816 gpu->rbbmtimer_clk = msm_clk_bulk_get_clock(gpu->grp_clks,817 gpu->nr_clocks, "rbbmtimer");818 819 return 0;820}821 822/* Return a new address space for a msm_drm_private instance */823struct msm_gem_address_space *824msm_gpu_create_private_address_space(struct msm_gpu *gpu, struct task_struct *task)825{826 struct msm_gem_address_space *aspace = NULL;827 if (!gpu)828 return NULL;829 830 /*831 * If the target doesn't support private address spaces then return832 * the global one833 */834 if (gpu->funcs->create_private_address_space) {835 aspace = gpu->funcs->create_private_address_space(gpu);836 if (!IS_ERR(aspace))837 aspace->pid = get_pid(task_pid(task));838 }839 840 if (IS_ERR_OR_NULL(aspace))841 aspace = msm_gem_address_space_get(gpu->aspace);842 843 return aspace;844}845 846int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,847 struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs,848 const char *name, struct msm_gpu_config *config)849{850 struct msm_drm_private *priv = drm->dev_private;851 int i, ret, nr_rings = config->nr_rings;852 void *memptrs;853 uint64_t memptrs_iova;854 855 if (WARN_ON(gpu->num_perfcntrs > ARRAY_SIZE(gpu->last_cntrs)))856 gpu->num_perfcntrs = ARRAY_SIZE(gpu->last_cntrs);857 858 gpu->dev = drm;859 gpu->funcs = funcs;860 gpu->name = name;861 862 gpu->worker = kthread_create_worker(0, "gpu-worker");863 if (IS_ERR(gpu->worker)) {864 ret = PTR_ERR(gpu->worker);865 gpu->worker = NULL;866 goto fail;867 }868 869 sched_set_fifo_low(gpu->worker->task);870 871 mutex_init(&gpu->active_lock);872 mutex_init(&gpu->lock);873 init_waitqueue_head(&gpu->retire_event);874 kthread_init_work(&gpu->retire_work, retire_worker);875 kthread_init_work(&gpu->recover_work, recover_worker);876 kthread_init_work(&gpu->fault_work, fault_worker);877 878 priv->hangcheck_period = DRM_MSM_HANGCHECK_DEFAULT_PERIOD;879 880 /*881 * If progress detection is supported, halve the hangcheck timer882 * duration, as it takes two iterations of the hangcheck handler883 * to detect a hang.884 */885 if (funcs->progress)886 priv->hangcheck_period /= 2;887 888 timer_setup(&gpu->hangcheck_timer, hangcheck_handler, 0);889 890 spin_lock_init(&gpu->perf_lock);891 892 893 /* Map registers: */894 gpu->mmio = msm_ioremap(pdev, config->ioname);895 if (IS_ERR(gpu->mmio)) {896 ret = PTR_ERR(gpu->mmio);897 goto fail;898 }899 900 /* Get Interrupt: */901 gpu->irq = platform_get_irq(pdev, 0);902 if (gpu->irq < 0) {903 ret = gpu->irq;904 goto fail;905 }906 907 ret = devm_request_irq(&pdev->dev, gpu->irq, irq_handler,908 IRQF_TRIGGER_HIGH, "gpu-irq", gpu);909 if (ret) {910 DRM_DEV_ERROR(drm->dev, "failed to request IRQ%u: %d\n", gpu->irq, ret);911 goto fail;912 }913 914 ret = get_clocks(pdev, gpu);915 if (ret)916 goto fail;917 918 gpu->ebi1_clk = msm_clk_get(pdev, "bus");919 DBG("ebi1_clk: %p", gpu->ebi1_clk);920 if (IS_ERR(gpu->ebi1_clk))921 gpu->ebi1_clk = NULL;922 923 /* Acquire regulators: */924 gpu->gpu_reg = devm_regulator_get(&pdev->dev, "vdd");925 DBG("gpu_reg: %p", gpu->gpu_reg);926 if (IS_ERR(gpu->gpu_reg))927 gpu->gpu_reg = NULL;928 929 gpu->gpu_cx = devm_regulator_get(&pdev->dev, "vddcx");930 DBG("gpu_cx: %p", gpu->gpu_cx);931 if (IS_ERR(gpu->gpu_cx))932 gpu->gpu_cx = NULL;933 934 platform_set_drvdata(pdev, &gpu->adreno_smmu);935 936 msm_devfreq_init(gpu);937 938 939 gpu->aspace = gpu->funcs->create_address_space(gpu, pdev);940 941 if (gpu->aspace == NULL)942 DRM_DEV_INFO(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name);943 else if (IS_ERR(gpu->aspace)) {944 ret = PTR_ERR(gpu->aspace);945 goto fail;946 }947 948 memptrs = msm_gem_kernel_new(drm,949 sizeof(struct msm_rbmemptrs) * nr_rings,950 check_apriv(gpu, MSM_BO_WC), gpu->aspace, &gpu->memptrs_bo,951 &memptrs_iova);952 953 if (IS_ERR(memptrs)) {954 ret = PTR_ERR(memptrs);955 DRM_DEV_ERROR(drm->dev, "could not allocate memptrs: %d\n", ret);956 goto fail;957 }958 959 msm_gem_object_set_name(gpu->memptrs_bo, "memptrs");960 961 if (nr_rings > ARRAY_SIZE(gpu->rb)) {962 DRM_DEV_INFO_ONCE(drm->dev, "Only creating %zu ringbuffers\n",963 ARRAY_SIZE(gpu->rb));964 nr_rings = ARRAY_SIZE(gpu->rb);965 }966 967 /* Create ringbuffer(s): */968 for (i = 0; i < nr_rings; i++) {969 gpu->rb[i] = msm_ringbuffer_new(gpu, i, memptrs, memptrs_iova);970 971 if (IS_ERR(gpu->rb[i])) {972 ret = PTR_ERR(gpu->rb[i]);973 DRM_DEV_ERROR(drm->dev,974 "could not create ringbuffer %d: %d\n", i, ret);975 goto fail;976 }977 978 memptrs += sizeof(struct msm_rbmemptrs);979 memptrs_iova += sizeof(struct msm_rbmemptrs);980 }981 982 gpu->nr_rings = nr_rings;983 984 refcount_set(&gpu->sysprof_active, 1);985 986 return 0;987 988fail:989 for (i = 0; i < ARRAY_SIZE(gpu->rb); i++) {990 msm_ringbuffer_destroy(gpu->rb[i]);991 gpu->rb[i] = NULL;992 }993 994 msm_gem_kernel_put(gpu->memptrs_bo, gpu->aspace);995 996 platform_set_drvdata(pdev, NULL);997 return ret;998}999 1000void msm_gpu_cleanup(struct msm_gpu *gpu)1001{1002 int i;1003 1004 DBG("%s", gpu->name);1005 1006 for (i = 0; i < ARRAY_SIZE(gpu->rb); i++) {1007 msm_ringbuffer_destroy(gpu->rb[i]);1008 gpu->rb[i] = NULL;1009 }1010 1011 msm_gem_kernel_put(gpu->memptrs_bo, gpu->aspace);1012 1013 if (!IS_ERR_OR_NULL(gpu->aspace)) {1014 gpu->aspace->mmu->funcs->detach(gpu->aspace->mmu);1015 msm_gem_address_space_put(gpu->aspace);1016 }1017 1018 if (gpu->worker) {1019 kthread_destroy_worker(gpu->worker);1020 }1021 1022 msm_devfreq_cleanup(gpu);1023 1024 platform_set_drvdata(gpu->pdev, NULL);1025}1026