brintos

brintos / linux-shallow public Read only

0
0
Text · 8.4 KiB · 481217c Raw
315 lines · c
1/*2 * Copyright 2021 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 */23 24#include "sienna_cichlid.h"25#include "amdgpu_reset.h"26#include "amdgpu_amdkfd.h"27#include "amdgpu_dpm.h"28#include "amdgpu_job.h"29#include "amdgpu_ring.h"30#include "amdgpu_ras.h"31#include "amdgpu_psp.h"32#include "amdgpu_xgmi.h"33 34static bool sienna_cichlid_is_mode2_default(struct amdgpu_reset_control *reset_ctl)35{36#if 037	struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle;38 39	if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(11, 0, 7) &&40	    adev->pm.fw_version >= 0x3a5500 && !amdgpu_sriov_vf(adev))41		return true;42#endif43	return amdgpu_reset_method == AMD_RESET_METHOD_MODE2;44}45 46static struct amdgpu_reset_handler *47sienna_cichlid_get_reset_handler(struct amdgpu_reset_control *reset_ctl,48			    struct amdgpu_reset_context *reset_context)49{50	struct amdgpu_reset_handler *handler;51	int i;52 53	if (reset_context->method != AMD_RESET_METHOD_NONE) {54		for_each_handler(i, handler, reset_ctl)	{55			if (handler->reset_method == reset_context->method)56				return handler;57		}58	}59 60	if (sienna_cichlid_is_mode2_default(reset_ctl)) {61		for_each_handler(i, handler, reset_ctl)	{62			if (handler->reset_method == AMD_RESET_METHOD_MODE2)63				return handler;64		}65	}66 67	return NULL;68}69 70static int sienna_cichlid_mode2_suspend_ip(struct amdgpu_device *adev)71{72	int r, i;73 74	amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);75	amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);76 77	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {78		if (!(adev->ip_blocks[i].version->type ==79			      AMD_IP_BLOCK_TYPE_GFX ||80		      adev->ip_blocks[i].version->type ==81			      AMD_IP_BLOCK_TYPE_SDMA))82			continue;83 84		r = adev->ip_blocks[i].version->funcs->suspend(adev);85 86		if (r) {87			dev_err(adev->dev,88				"suspend of IP block <%s> failed %d\n",89				adev->ip_blocks[i].version->funcs->name, r);90			return r;91		}92		adev->ip_blocks[i].status.hw = false;93	}94 95	return 0;96}97 98static int99sienna_cichlid_mode2_prepare_hwcontext(struct amdgpu_reset_control *reset_ctl,100				  struct amdgpu_reset_context *reset_context)101{102	int r = 0;103	struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle;104 105	if (!amdgpu_sriov_vf(adev)) {106		if (adev->gfxhub.funcs->mode2_save_regs)107			adev->gfxhub.funcs->mode2_save_regs(adev);108		if (adev->gfxhub.funcs->halt)109			adev->gfxhub.funcs->halt(adev);110		r = sienna_cichlid_mode2_suspend_ip(adev);111	}112 113	return r;114}115 116static void sienna_cichlid_async_reset(struct work_struct *work)117{118	struct amdgpu_reset_handler *handler;119	struct amdgpu_reset_control *reset_ctl =120		container_of(work, struct amdgpu_reset_control, reset_work);121	struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle;122	int i;123 124	for_each_handler(i, handler, reset_ctl)	{125		if (handler->reset_method == reset_ctl->active_reset) {126			dev_dbg(adev->dev, "Resetting device\n");127			handler->do_reset(adev);128			break;129		}130	}131}132 133static int sienna_cichlid_mode2_reset(struct amdgpu_device *adev)134{135	/* disable BM */136	pci_clear_master(adev->pdev);137	return amdgpu_dpm_mode2_reset(adev);138}139 140static int141sienna_cichlid_mode2_perform_reset(struct amdgpu_reset_control *reset_ctl,142			      struct amdgpu_reset_context *reset_context)143{144	struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle;145	int r;146 147	r = sienna_cichlid_mode2_reset(adev);148	if (r) {149		dev_err(adev->dev,150			"ASIC reset failed with error, %d ", r);151	}152	return r;153}154 155static int sienna_cichlid_mode2_restore_ip(struct amdgpu_device *adev)156{157	int i, r;158	struct psp_context *psp = &adev->psp;159 160	r = psp_rlc_autoload_start(psp);161	if (r) {162		dev_err(adev->dev, "Failed to start rlc autoload\n");163		return r;164	}165 166	/* Reinit GFXHUB */167	if (adev->gfxhub.funcs->mode2_restore_regs)168		adev->gfxhub.funcs->mode2_restore_regs(adev);169	adev->gfxhub.funcs->init(adev);170	r = adev->gfxhub.funcs->gart_enable(adev);171	if (r) {172		dev_err(adev->dev, "GFXHUB gart reenable failed after reset\n");173		return r;174	}175 176	for (i = 0; i < adev->num_ip_blocks; i++) {177		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH) {178			r = adev->ip_blocks[i].version->funcs->resume(adev);179			if (r) {180				dev_err(adev->dev,181					"resume of IP block <%s> failed %d\n",182					adev->ip_blocks[i].version->funcs->name, r);183				return r;184			}185 186			adev->ip_blocks[i].status.hw = true;187		}188	}189 190	for (i = 0; i < adev->num_ip_blocks; i++) {191		if (!(adev->ip_blocks[i].version->type ==192			      AMD_IP_BLOCK_TYPE_GFX ||193		      adev->ip_blocks[i].version->type ==194			      AMD_IP_BLOCK_TYPE_SDMA))195			continue;196		r = adev->ip_blocks[i].version->funcs->resume(adev);197		if (r) {198			dev_err(adev->dev,199				"resume of IP block <%s> failed %d\n",200				adev->ip_blocks[i].version->funcs->name, r);201			return r;202		}203 204		adev->ip_blocks[i].status.hw = true;205	}206 207	for (i = 0; i < adev->num_ip_blocks; i++) {208		if (!(adev->ip_blocks[i].version->type ==209			      AMD_IP_BLOCK_TYPE_GFX ||210		      adev->ip_blocks[i].version->type ==211			      AMD_IP_BLOCK_TYPE_SDMA))212			continue;213 214		if (adev->ip_blocks[i].version->funcs->late_init) {215			r = adev->ip_blocks[i].version->funcs->late_init(216				(void *)adev);217			if (r) {218				dev_err(adev->dev,219					"late_init of IP block <%s> failed %d after reset\n",220					adev->ip_blocks[i].version->funcs->name,221					r);222				return r;223			}224		}225		adev->ip_blocks[i].status.late_initialized = true;226	}227 228	amdgpu_device_set_cg_state(adev, AMD_CG_STATE_GATE);229	amdgpu_device_set_pg_state(adev, AMD_PG_STATE_GATE);230 231	return r;232}233 234static int235sienna_cichlid_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,236				  struct amdgpu_reset_context *reset_context)237{238	int r;239	struct amdgpu_device *tmp_adev = (struct amdgpu_device *)reset_ctl->handle;240 241	dev_info(tmp_adev->dev,242			"GPU reset succeeded, trying to resume\n");243	r = sienna_cichlid_mode2_restore_ip(tmp_adev);244	if (r)245		goto end;246 247	/*248	* Add this ASIC as tracked as reset was already249	* complete successfully.250	*/251	amdgpu_register_gpu_instance(tmp_adev);252 253	/* Resume RAS */254	amdgpu_ras_resume(tmp_adev);255 256	amdgpu_irq_gpu_reset_resume_helper(tmp_adev);257 258	r = amdgpu_ib_ring_tests(tmp_adev);259	if (r) {260		dev_err(tmp_adev->dev,261			"ib ring test failed (%d).\n", r);262		r = -EAGAIN;263		goto end;264	}265 266end:267	if (r)268		return -EAGAIN;269	else270		return r;271}272 273static struct amdgpu_reset_handler sienna_cichlid_mode2_handler = {274	.reset_method		= AMD_RESET_METHOD_MODE2,275	.prepare_env		= NULL,276	.prepare_hwcontext	= sienna_cichlid_mode2_prepare_hwcontext,277	.perform_reset		= sienna_cichlid_mode2_perform_reset,278	.restore_hwcontext	= sienna_cichlid_mode2_restore_hwcontext,279	.restore_env		= NULL,280	.do_reset		= sienna_cichlid_mode2_reset,281};282 283static struct amdgpu_reset_handler284	*sienna_cichlid_rst_handlers[AMDGPU_RESET_MAX_HANDLERS] = {285		&sienna_cichlid_mode2_handler,286	};287 288int sienna_cichlid_reset_init(struct amdgpu_device *adev)289{290	struct amdgpu_reset_control *reset_ctl;291 292	reset_ctl = kzalloc(sizeof(*reset_ctl), GFP_KERNEL);293	if (!reset_ctl)294		return -ENOMEM;295 296	reset_ctl->handle = adev;297	reset_ctl->async_reset = sienna_cichlid_async_reset;298	reset_ctl->active_reset = AMD_RESET_METHOD_NONE;299	reset_ctl->get_reset_handler = sienna_cichlid_get_reset_handler;300 301	INIT_WORK(&reset_ctl->reset_work, reset_ctl->async_reset);302	/* Only mode2 is handled through reset control now */303	reset_ctl->reset_handlers = &sienna_cichlid_rst_handlers;304	adev->reset_cntl = reset_ctl;305 306	return 0;307}308 309int sienna_cichlid_reset_fini(struct amdgpu_device *adev)310{311	kfree(adev->reset_cntl);312	adev->reset_cntl = NULL;313	return 0;314}315