brintos

brintos / linux-shallow public Read only

0
0
Text · 23.5 KiB · a274b84 Raw
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