Home | History | Annotate | Line # | Download | only in amdgpu
      1 /*	$NetBSD: amdgpu_rlc.c,v 1.3 2021/12/19 12:21:29 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2014 Advanced Micro Devices, Inc.
      5  * Copyright 2008 Red Hat Inc.
      6  * Copyright 2009 Jerome Glisse.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the "Software"),
     10  * to deal in the Software without restriction, including without limitation
     11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     12  * and/or sell copies of the Software, and to permit persons to whom the
     13  * Software is furnished to do so, subject to the following conditions:
     14  *
     15  * The above copyright notice and this permission notice shall be included in
     16  * all copies or substantial portions of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     21  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     22  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     24  * OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  */
     27 #include <sys/cdefs.h>
     28 __KERNEL_RCSID(0, "$NetBSD: amdgpu_rlc.c,v 1.3 2021/12/19 12:21:29 riastradh Exp $");
     29 
     30 #include <linux/firmware.h>
     31 #include "amdgpu.h"
     32 #include "amdgpu_gfx.h"
     33 #include "amdgpu_rlc.h"
     34 
     35 /**
     36  * amdgpu_gfx_rlc_enter_safe_mode - Set RLC into safe mode
     37  *
     38  * @adev: amdgpu_device pointer
     39  *
     40  * Set RLC enter into safe mode if RLC is enabled and haven't in safe mode.
     41  */
     42 void amdgpu_gfx_rlc_enter_safe_mode(struct amdgpu_device *adev)
     43 {
     44 	if (adev->gfx.rlc.in_safe_mode)
     45 		return;
     46 
     47 	/* if RLC is not enabled, do nothing */
     48 	if (!adev->gfx.rlc.funcs->is_rlc_enabled(adev))
     49 		return;
     50 
     51 	if (adev->cg_flags &
     52 	    (AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_MGCG |
     53 	     AMD_CG_SUPPORT_GFX_3D_CGCG)) {
     54 		adev->gfx.rlc.funcs->set_safe_mode(adev);
     55 		adev->gfx.rlc.in_safe_mode = true;
     56 	}
     57 }
     58 
     59 /**
     60  * amdgpu_gfx_rlc_exit_safe_mode - Set RLC out of safe mode
     61  *
     62  * @adev: amdgpu_device pointer
     63  *
     64  * Set RLC exit safe mode if RLC is enabled and have entered into safe mode.
     65  */
     66 void amdgpu_gfx_rlc_exit_safe_mode(struct amdgpu_device *adev)
     67 {
     68 	if (!(adev->gfx.rlc.in_safe_mode))
     69 		return;
     70 
     71 	/* if RLC is not enabled, do nothing */
     72 	if (!adev->gfx.rlc.funcs->is_rlc_enabled(adev))
     73 		return;
     74 
     75 	if (adev->cg_flags &
     76 	    (AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_MGCG |
     77 	     AMD_CG_SUPPORT_GFX_3D_CGCG)) {
     78 		adev->gfx.rlc.funcs->unset_safe_mode(adev);
     79 		adev->gfx.rlc.in_safe_mode = false;
     80 	}
     81 }
     82 
     83 /**
     84  * amdgpu_gfx_rlc_init_sr - Init save restore block
     85  *
     86  * @adev: amdgpu_device pointer
     87  * @dws: the size of save restore block
     88  *
     89  * Allocate and setup value to save restore block of rlc.
     90  * Returns 0 on succeess or negative error code if allocate failed.
     91  */
     92 int amdgpu_gfx_rlc_init_sr(struct amdgpu_device *adev, u32 dws)
     93 {
     94 	const u32 *src_ptr;
     95 	volatile u32 *dst_ptr;
     96 	u32 i;
     97 	int r;
     98 
     99 	/* allocate save restore block */
    100 	r = amdgpu_bo_create_reserved(adev, dws * 4, PAGE_SIZE,
    101 				      AMDGPU_GEM_DOMAIN_VRAM,
    102 				      &adev->gfx.rlc.save_restore_obj,
    103 				      &adev->gfx.rlc.save_restore_gpu_addr,
    104 				      (void **)__UNVOLATILE(&adev->gfx.rlc.sr_ptr));
    105 	if (r) {
    106 		dev_warn(adev->dev, "(%d) create RLC sr bo failed\n", r);
    107 		amdgpu_gfx_rlc_fini(adev);
    108 		return r;
    109 	}
    110 
    111 	/* write the sr buffer */
    112 	src_ptr = adev->gfx.rlc.reg_list;
    113 	dst_ptr = adev->gfx.rlc.sr_ptr;
    114 	for (i = 0; i < adev->gfx.rlc.reg_list_size; i++)
    115 		dst_ptr[i] = cpu_to_le32(src_ptr[i]);
    116 	amdgpu_bo_kunmap(adev->gfx.rlc.save_restore_obj);
    117 	amdgpu_bo_unreserve(adev->gfx.rlc.save_restore_obj);
    118 
    119 	return 0;
    120 }
    121 
    122 /**
    123  * amdgpu_gfx_rlc_init_csb - Init clear state block
    124  *
    125  * @adev: amdgpu_device pointer
    126  *
    127  * Allocate and setup value to clear state block of rlc.
    128  * Returns 0 on succeess or negative error code if allocate failed.
    129  */
    130 int amdgpu_gfx_rlc_init_csb(struct amdgpu_device *adev)
    131 {
    132 	u32 dws;
    133 	int r;
    134 
    135 	/* allocate clear state block */
    136 	adev->gfx.rlc.clear_state_size = dws = adev->gfx.rlc.funcs->get_csb_size(adev);
    137 	r = amdgpu_bo_create_kernel(adev, dws * 4, PAGE_SIZE,
    138 				      AMDGPU_GEM_DOMAIN_VRAM,
    139 				      &adev->gfx.rlc.clear_state_obj,
    140 				      &adev->gfx.rlc.clear_state_gpu_addr,
    141 				      (void **)__UNVOLATILE(&adev->gfx.rlc.cs_ptr));
    142 	if (r) {
    143 		dev_err(adev->dev, "(%d) failed to create rlc csb bo\n", r);
    144 		amdgpu_gfx_rlc_fini(adev);
    145 		return r;
    146 	}
    147 
    148 	return 0;
    149 }
    150 
    151 /**
    152  * amdgpu_gfx_rlc_init_cpt - Init cp table
    153  *
    154  * @adev: amdgpu_device pointer
    155  *
    156  * Allocate and setup value to cp table of rlc.
    157  * Returns 0 on succeess or negative error code if allocate failed.
    158  */
    159 int amdgpu_gfx_rlc_init_cpt(struct amdgpu_device *adev)
    160 {
    161 	int r;
    162 
    163 	r = amdgpu_bo_create_reserved(adev, adev->gfx.rlc.cp_table_size,
    164 				      PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
    165 				      &adev->gfx.rlc.cp_table_obj,
    166 				      &adev->gfx.rlc.cp_table_gpu_addr,
    167 				      (void **)__UNVOLATILE(&adev->gfx.rlc.cp_table_ptr));
    168 	if (r) {
    169 		dev_err(adev->dev, "(%d) failed to create cp table bo\n", r);
    170 		amdgpu_gfx_rlc_fini(adev);
    171 		return r;
    172 	}
    173 
    174 	/* set up the cp table */
    175 	amdgpu_gfx_rlc_setup_cp_table(adev);
    176 	amdgpu_bo_kunmap(adev->gfx.rlc.cp_table_obj);
    177 	amdgpu_bo_unreserve(adev->gfx.rlc.cp_table_obj);
    178 
    179 	return 0;
    180 }
    181 
    182 /**
    183  * amdgpu_gfx_rlc_setup_cp_table - setup cp the buffer of cp table
    184  *
    185  * @adev: amdgpu_device pointer
    186  *
    187  * Write cp firmware data into cp table.
    188  */
    189 void amdgpu_gfx_rlc_setup_cp_table(struct amdgpu_device *adev)
    190 {
    191 	const __le32 *fw_data;
    192 	volatile u32 *dst_ptr;
    193 	int me, i, max_me;
    194 	u32 bo_offset = 0;
    195 	u32 table_offset, table_size;
    196 
    197 	max_me = adev->gfx.rlc.funcs->get_cp_table_num(adev);
    198 
    199 	/* write the cp table buffer */
    200 	dst_ptr = adev->gfx.rlc.cp_table_ptr;
    201 	for (me = 0; me < max_me; me++) {
    202 		if (me == 0) {
    203 			const struct gfx_firmware_header_v1_0 *hdr =
    204 				(const struct gfx_firmware_header_v1_0 *)adev->gfx.ce_fw->data;
    205 			fw_data = (const __le32 *)
    206 				(adev->gfx.ce_fw->data +
    207 				 le32_to_cpu(hdr->header.ucode_array_offset_bytes));
    208 			table_offset = le32_to_cpu(hdr->jt_offset);
    209 			table_size = le32_to_cpu(hdr->jt_size);
    210 		} else if (me == 1) {
    211 			const struct gfx_firmware_header_v1_0 *hdr =
    212 				(const struct gfx_firmware_header_v1_0 *)adev->gfx.pfp_fw->data;
    213 			fw_data = (const __le32 *)
    214 				(adev->gfx.pfp_fw->data +
    215 				 le32_to_cpu(hdr->header.ucode_array_offset_bytes));
    216 			table_offset = le32_to_cpu(hdr->jt_offset);
    217 			table_size = le32_to_cpu(hdr->jt_size);
    218 		} else if (me == 2) {
    219 			const struct gfx_firmware_header_v1_0 *hdr =
    220 				(const struct gfx_firmware_header_v1_0 *)adev->gfx.me_fw->data;
    221 			fw_data = (const __le32 *)
    222 				(adev->gfx.me_fw->data +
    223 				 le32_to_cpu(hdr->header.ucode_array_offset_bytes));
    224 			table_offset = le32_to_cpu(hdr->jt_offset);
    225 			table_size = le32_to_cpu(hdr->jt_size);
    226 		} else if (me == 3) {
    227 			const struct gfx_firmware_header_v1_0 *hdr =
    228 				(const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
    229 			fw_data = (const __le32 *)
    230 				(adev->gfx.mec_fw->data +
    231 				 le32_to_cpu(hdr->header.ucode_array_offset_bytes));
    232 			table_offset = le32_to_cpu(hdr->jt_offset);
    233 			table_size = le32_to_cpu(hdr->jt_size);
    234 		} else  if (me == 4) {
    235 			const struct gfx_firmware_header_v1_0 *hdr =
    236 				(const struct gfx_firmware_header_v1_0 *)adev->gfx.mec2_fw->data;
    237 			fw_data = (const __le32 *)
    238 				(adev->gfx.mec2_fw->data +
    239 				 le32_to_cpu(hdr->header.ucode_array_offset_bytes));
    240 			table_offset = le32_to_cpu(hdr->jt_offset);
    241 			table_size = le32_to_cpu(hdr->jt_size);
    242 		}
    243 
    244 		for (i = 0; i < table_size; i ++) {
    245 			dst_ptr[bo_offset + i] =
    246 				cpu_to_le32(le32_to_cpu(fw_data[table_offset + i]));
    247 		}
    248 
    249 		bo_offset += table_size;
    250 	}
    251 }
    252 
    253 /**
    254  * amdgpu_gfx_rlc_fini - Free BO which used for RLC
    255  *
    256  * @adev: amdgpu_device pointer
    257  *
    258  * Free three BO which is used for rlc_save_restore_block, rlc_clear_state_block
    259  * and rlc_jump_table_block.
    260  */
    261 void amdgpu_gfx_rlc_fini(struct amdgpu_device *adev)
    262 {
    263 	/* save restore block */
    264 	if (adev->gfx.rlc.save_restore_obj) {
    265 		amdgpu_bo_free_kernel(&adev->gfx.rlc.save_restore_obj,
    266 				      &adev->gfx.rlc.save_restore_gpu_addr,
    267 				      (void **)__UNVOLATILE(&adev->gfx.rlc.sr_ptr));
    268 	}
    269 
    270 	/* clear state block */
    271 	amdgpu_bo_free_kernel(&adev->gfx.rlc.clear_state_obj,
    272 			      &adev->gfx.rlc.clear_state_gpu_addr,
    273 			      (void **)__UNVOLATILE(&adev->gfx.rlc.cs_ptr));
    274 
    275 	/* jump table block */
    276 	amdgpu_bo_free_kernel(&adev->gfx.rlc.cp_table_obj,
    277 			      &adev->gfx.rlc.cp_table_gpu_addr,
    278 			      (void **)__UNVOLATILE(&adev->gfx.rlc.cp_table_ptr));
    279 }
    280