18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright 2010 Advanced Micro Devices, Inc.
38c2ecf20Sopenharmony_ci * Copyright 2008 Red Hat Inc.
48c2ecf20Sopenharmony_ci * Copyright 2009 Jerome Glisse.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
78c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
88c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation
98c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
108c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
118c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
148c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software.
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
178c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
188c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
198c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
208c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
218c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
228c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * Authors: Dave Airlie
258c2ecf20Sopenharmony_ci *          Alex Deucher
268c2ecf20Sopenharmony_ci *          Jerome Glisse
278c2ecf20Sopenharmony_ci */
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#include "radeon.h"
308c2ecf20Sopenharmony_ci#include "radeon_asic.h"
318c2ecf20Sopenharmony_ci#include "evergreend.h"
328c2ecf20Sopenharmony_ci#include "evergreen_reg_safe.h"
338c2ecf20Sopenharmony_ci#include "cayman_reg_safe.h"
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define MAX(a,b)                   (((a)>(b))?(a):(b))
368c2ecf20Sopenharmony_ci#define MIN(a,b)                   (((a)<(b))?(a):(b))
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#define REG_SAFE_BM_SIZE ARRAY_SIZE(evergreen_reg_safe_bm)
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ciint r600_dma_cs_next_reloc(struct radeon_cs_parser *p,
418c2ecf20Sopenharmony_ci			   struct radeon_bo_list **cs_reloc);
428c2ecf20Sopenharmony_cistruct evergreen_cs_track {
438c2ecf20Sopenharmony_ci	u32			group_size;
448c2ecf20Sopenharmony_ci	u32			nbanks;
458c2ecf20Sopenharmony_ci	u32			npipes;
468c2ecf20Sopenharmony_ci	u32			row_size;
478c2ecf20Sopenharmony_ci	/* value we track */
488c2ecf20Sopenharmony_ci	u32			nsamples;		/* unused */
498c2ecf20Sopenharmony_ci	struct radeon_bo	*cb_color_bo[12];
508c2ecf20Sopenharmony_ci	u32			cb_color_bo_offset[12];
518c2ecf20Sopenharmony_ci	struct radeon_bo	*cb_color_fmask_bo[8];	/* unused */
528c2ecf20Sopenharmony_ci	struct radeon_bo	*cb_color_cmask_bo[8];	/* unused */
538c2ecf20Sopenharmony_ci	u32			cb_color_info[12];
548c2ecf20Sopenharmony_ci	u32			cb_color_view[12];
558c2ecf20Sopenharmony_ci	u32			cb_color_pitch[12];
568c2ecf20Sopenharmony_ci	u32			cb_color_slice[12];
578c2ecf20Sopenharmony_ci	u32			cb_color_slice_idx[12];
588c2ecf20Sopenharmony_ci	u32			cb_color_attrib[12];
598c2ecf20Sopenharmony_ci	u32			cb_color_cmask_slice[8];/* unused */
608c2ecf20Sopenharmony_ci	u32			cb_color_fmask_slice[8];/* unused */
618c2ecf20Sopenharmony_ci	u32			cb_target_mask;
628c2ecf20Sopenharmony_ci	u32			cb_shader_mask; /* unused */
638c2ecf20Sopenharmony_ci	u32			vgt_strmout_config;
648c2ecf20Sopenharmony_ci	u32			vgt_strmout_buffer_config;
658c2ecf20Sopenharmony_ci	struct radeon_bo	*vgt_strmout_bo[4];
668c2ecf20Sopenharmony_ci	u32			vgt_strmout_bo_offset[4];
678c2ecf20Sopenharmony_ci	u32			vgt_strmout_size[4];
688c2ecf20Sopenharmony_ci	u32			db_depth_control;
698c2ecf20Sopenharmony_ci	u32			db_depth_view;
708c2ecf20Sopenharmony_ci	u32			db_depth_slice;
718c2ecf20Sopenharmony_ci	u32			db_depth_size;
728c2ecf20Sopenharmony_ci	u32			db_z_info;
738c2ecf20Sopenharmony_ci	u32			db_z_read_offset;
748c2ecf20Sopenharmony_ci	u32			db_z_write_offset;
758c2ecf20Sopenharmony_ci	struct radeon_bo	*db_z_read_bo;
768c2ecf20Sopenharmony_ci	struct radeon_bo	*db_z_write_bo;
778c2ecf20Sopenharmony_ci	u32			db_s_info;
788c2ecf20Sopenharmony_ci	u32			db_s_read_offset;
798c2ecf20Sopenharmony_ci	u32			db_s_write_offset;
808c2ecf20Sopenharmony_ci	struct radeon_bo	*db_s_read_bo;
818c2ecf20Sopenharmony_ci	struct radeon_bo	*db_s_write_bo;
828c2ecf20Sopenharmony_ci	bool			sx_misc_kill_all_prims;
838c2ecf20Sopenharmony_ci	bool			cb_dirty;
848c2ecf20Sopenharmony_ci	bool			db_dirty;
858c2ecf20Sopenharmony_ci	bool			streamout_dirty;
868c2ecf20Sopenharmony_ci	u32			htile_offset;
878c2ecf20Sopenharmony_ci	u32			htile_surface;
888c2ecf20Sopenharmony_ci	struct radeon_bo	*htile_bo;
898c2ecf20Sopenharmony_ci	unsigned long		indirect_draw_buffer_size;
908c2ecf20Sopenharmony_ci	const unsigned		*reg_safe_bm;
918c2ecf20Sopenharmony_ci};
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cistatic u32 evergreen_cs_get_aray_mode(u32 tiling_flags)
948c2ecf20Sopenharmony_ci{
958c2ecf20Sopenharmony_ci	if (tiling_flags & RADEON_TILING_MACRO)
968c2ecf20Sopenharmony_ci		return ARRAY_2D_TILED_THIN1;
978c2ecf20Sopenharmony_ci	else if (tiling_flags & RADEON_TILING_MICRO)
988c2ecf20Sopenharmony_ci		return ARRAY_1D_TILED_THIN1;
998c2ecf20Sopenharmony_ci	else
1008c2ecf20Sopenharmony_ci		return ARRAY_LINEAR_GENERAL;
1018c2ecf20Sopenharmony_ci}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistatic u32 evergreen_cs_get_num_banks(u32 nbanks)
1048c2ecf20Sopenharmony_ci{
1058c2ecf20Sopenharmony_ci	switch (nbanks) {
1068c2ecf20Sopenharmony_ci	case 2:
1078c2ecf20Sopenharmony_ci		return ADDR_SURF_2_BANK;
1088c2ecf20Sopenharmony_ci	case 4:
1098c2ecf20Sopenharmony_ci		return ADDR_SURF_4_BANK;
1108c2ecf20Sopenharmony_ci	case 8:
1118c2ecf20Sopenharmony_ci	default:
1128c2ecf20Sopenharmony_ci		return ADDR_SURF_8_BANK;
1138c2ecf20Sopenharmony_ci	case 16:
1148c2ecf20Sopenharmony_ci		return ADDR_SURF_16_BANK;
1158c2ecf20Sopenharmony_ci	}
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistatic void evergreen_cs_track_init(struct evergreen_cs_track *track)
1198c2ecf20Sopenharmony_ci{
1208c2ecf20Sopenharmony_ci	int i;
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	for (i = 0; i < 8; i++) {
1238c2ecf20Sopenharmony_ci		track->cb_color_fmask_bo[i] = NULL;
1248c2ecf20Sopenharmony_ci		track->cb_color_cmask_bo[i] = NULL;
1258c2ecf20Sopenharmony_ci		track->cb_color_cmask_slice[i] = 0;
1268c2ecf20Sopenharmony_ci		track->cb_color_fmask_slice[i] = 0;
1278c2ecf20Sopenharmony_ci	}
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	for (i = 0; i < 12; i++) {
1308c2ecf20Sopenharmony_ci		track->cb_color_bo[i] = NULL;
1318c2ecf20Sopenharmony_ci		track->cb_color_bo_offset[i] = 0xFFFFFFFF;
1328c2ecf20Sopenharmony_ci		track->cb_color_info[i] = 0;
1338c2ecf20Sopenharmony_ci		track->cb_color_view[i] = 0xFFFFFFFF;
1348c2ecf20Sopenharmony_ci		track->cb_color_pitch[i] = 0;
1358c2ecf20Sopenharmony_ci		track->cb_color_slice[i] = 0xfffffff;
1368c2ecf20Sopenharmony_ci		track->cb_color_slice_idx[i] = 0;
1378c2ecf20Sopenharmony_ci	}
1388c2ecf20Sopenharmony_ci	track->cb_target_mask = 0xFFFFFFFF;
1398c2ecf20Sopenharmony_ci	track->cb_shader_mask = 0xFFFFFFFF;
1408c2ecf20Sopenharmony_ci	track->cb_dirty = true;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	track->db_depth_slice = 0xffffffff;
1438c2ecf20Sopenharmony_ci	track->db_depth_view = 0xFFFFC000;
1448c2ecf20Sopenharmony_ci	track->db_depth_size = 0xFFFFFFFF;
1458c2ecf20Sopenharmony_ci	track->db_depth_control = 0xFFFFFFFF;
1468c2ecf20Sopenharmony_ci	track->db_z_info = 0xFFFFFFFF;
1478c2ecf20Sopenharmony_ci	track->db_z_read_offset = 0xFFFFFFFF;
1488c2ecf20Sopenharmony_ci	track->db_z_write_offset = 0xFFFFFFFF;
1498c2ecf20Sopenharmony_ci	track->db_z_read_bo = NULL;
1508c2ecf20Sopenharmony_ci	track->db_z_write_bo = NULL;
1518c2ecf20Sopenharmony_ci	track->db_s_info = 0xFFFFFFFF;
1528c2ecf20Sopenharmony_ci	track->db_s_read_offset = 0xFFFFFFFF;
1538c2ecf20Sopenharmony_ci	track->db_s_write_offset = 0xFFFFFFFF;
1548c2ecf20Sopenharmony_ci	track->db_s_read_bo = NULL;
1558c2ecf20Sopenharmony_ci	track->db_s_write_bo = NULL;
1568c2ecf20Sopenharmony_ci	track->db_dirty = true;
1578c2ecf20Sopenharmony_ci	track->htile_bo = NULL;
1588c2ecf20Sopenharmony_ci	track->htile_offset = 0xFFFFFFFF;
1598c2ecf20Sopenharmony_ci	track->htile_surface = 0;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++) {
1628c2ecf20Sopenharmony_ci		track->vgt_strmout_size[i] = 0;
1638c2ecf20Sopenharmony_ci		track->vgt_strmout_bo[i] = NULL;
1648c2ecf20Sopenharmony_ci		track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
1658c2ecf20Sopenharmony_ci	}
1668c2ecf20Sopenharmony_ci	track->streamout_dirty = true;
1678c2ecf20Sopenharmony_ci	track->sx_misc_kill_all_prims = false;
1688c2ecf20Sopenharmony_ci}
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_cistruct eg_surface {
1718c2ecf20Sopenharmony_ci	/* value gathered from cs */
1728c2ecf20Sopenharmony_ci	unsigned	nbx;
1738c2ecf20Sopenharmony_ci	unsigned	nby;
1748c2ecf20Sopenharmony_ci	unsigned	format;
1758c2ecf20Sopenharmony_ci	unsigned	mode;
1768c2ecf20Sopenharmony_ci	unsigned	nbanks;
1778c2ecf20Sopenharmony_ci	unsigned	bankw;
1788c2ecf20Sopenharmony_ci	unsigned	bankh;
1798c2ecf20Sopenharmony_ci	unsigned	tsplit;
1808c2ecf20Sopenharmony_ci	unsigned	mtilea;
1818c2ecf20Sopenharmony_ci	unsigned	nsamples;
1828c2ecf20Sopenharmony_ci	/* output value */
1838c2ecf20Sopenharmony_ci	unsigned	bpe;
1848c2ecf20Sopenharmony_ci	unsigned	layer_size;
1858c2ecf20Sopenharmony_ci	unsigned	palign;
1868c2ecf20Sopenharmony_ci	unsigned	halign;
1878c2ecf20Sopenharmony_ci	unsigned long	base_align;
1888c2ecf20Sopenharmony_ci};
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_cistatic int evergreen_surface_check_linear(struct radeon_cs_parser *p,
1918c2ecf20Sopenharmony_ci					  struct eg_surface *surf,
1928c2ecf20Sopenharmony_ci					  const char *prefix)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	surf->layer_size = surf->nbx * surf->nby * surf->bpe * surf->nsamples;
1958c2ecf20Sopenharmony_ci	surf->base_align = surf->bpe;
1968c2ecf20Sopenharmony_ci	surf->palign = 1;
1978c2ecf20Sopenharmony_ci	surf->halign = 1;
1988c2ecf20Sopenharmony_ci	return 0;
1998c2ecf20Sopenharmony_ci}
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_cistatic int evergreen_surface_check_linear_aligned(struct radeon_cs_parser *p,
2028c2ecf20Sopenharmony_ci						  struct eg_surface *surf,
2038c2ecf20Sopenharmony_ci						  const char *prefix)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	struct evergreen_cs_track *track = p->track;
2068c2ecf20Sopenharmony_ci	unsigned palign;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	palign = MAX(64, track->group_size / surf->bpe);
2098c2ecf20Sopenharmony_ci	surf->layer_size = surf->nbx * surf->nby * surf->bpe * surf->nsamples;
2108c2ecf20Sopenharmony_ci	surf->base_align = track->group_size;
2118c2ecf20Sopenharmony_ci	surf->palign = palign;
2128c2ecf20Sopenharmony_ci	surf->halign = 1;
2138c2ecf20Sopenharmony_ci	if (surf->nbx & (palign - 1)) {
2148c2ecf20Sopenharmony_ci		if (prefix) {
2158c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d\n",
2168c2ecf20Sopenharmony_ci				 __func__, __LINE__, prefix, surf->nbx, palign);
2178c2ecf20Sopenharmony_ci		}
2188c2ecf20Sopenharmony_ci		return -EINVAL;
2198c2ecf20Sopenharmony_ci	}
2208c2ecf20Sopenharmony_ci	return 0;
2218c2ecf20Sopenharmony_ci}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_cistatic int evergreen_surface_check_1d(struct radeon_cs_parser *p,
2248c2ecf20Sopenharmony_ci				      struct eg_surface *surf,
2258c2ecf20Sopenharmony_ci				      const char *prefix)
2268c2ecf20Sopenharmony_ci{
2278c2ecf20Sopenharmony_ci	struct evergreen_cs_track *track = p->track;
2288c2ecf20Sopenharmony_ci	unsigned palign;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	palign = track->group_size / (8 * surf->bpe * surf->nsamples);
2318c2ecf20Sopenharmony_ci	palign = MAX(8, palign);
2328c2ecf20Sopenharmony_ci	surf->layer_size = surf->nbx * surf->nby * surf->bpe;
2338c2ecf20Sopenharmony_ci	surf->base_align = track->group_size;
2348c2ecf20Sopenharmony_ci	surf->palign = palign;
2358c2ecf20Sopenharmony_ci	surf->halign = 8;
2368c2ecf20Sopenharmony_ci	if ((surf->nbx & (palign - 1))) {
2378c2ecf20Sopenharmony_ci		if (prefix) {
2388c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d (%d %d %d)\n",
2398c2ecf20Sopenharmony_ci				 __func__, __LINE__, prefix, surf->nbx, palign,
2408c2ecf20Sopenharmony_ci				 track->group_size, surf->bpe, surf->nsamples);
2418c2ecf20Sopenharmony_ci		}
2428c2ecf20Sopenharmony_ci		return -EINVAL;
2438c2ecf20Sopenharmony_ci	}
2448c2ecf20Sopenharmony_ci	if ((surf->nby & (8 - 1))) {
2458c2ecf20Sopenharmony_ci		if (prefix) {
2468c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d %s height %d invalid must be aligned with 8\n",
2478c2ecf20Sopenharmony_ci				 __func__, __LINE__, prefix, surf->nby);
2488c2ecf20Sopenharmony_ci		}
2498c2ecf20Sopenharmony_ci		return -EINVAL;
2508c2ecf20Sopenharmony_ci	}
2518c2ecf20Sopenharmony_ci	return 0;
2528c2ecf20Sopenharmony_ci}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_cistatic int evergreen_surface_check_2d(struct radeon_cs_parser *p,
2558c2ecf20Sopenharmony_ci				      struct eg_surface *surf,
2568c2ecf20Sopenharmony_ci				      const char *prefix)
2578c2ecf20Sopenharmony_ci{
2588c2ecf20Sopenharmony_ci	struct evergreen_cs_track *track = p->track;
2598c2ecf20Sopenharmony_ci	unsigned palign, halign, tileb, slice_pt;
2608c2ecf20Sopenharmony_ci	unsigned mtile_pr, mtile_ps, mtileb;
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	tileb = 64 * surf->bpe * surf->nsamples;
2638c2ecf20Sopenharmony_ci	slice_pt = 1;
2648c2ecf20Sopenharmony_ci	if (tileb > surf->tsplit) {
2658c2ecf20Sopenharmony_ci		slice_pt = tileb / surf->tsplit;
2668c2ecf20Sopenharmony_ci	}
2678c2ecf20Sopenharmony_ci	tileb = tileb / slice_pt;
2688c2ecf20Sopenharmony_ci	/* macro tile width & height */
2698c2ecf20Sopenharmony_ci	palign = (8 * surf->bankw * track->npipes) * surf->mtilea;
2708c2ecf20Sopenharmony_ci	halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea;
2718c2ecf20Sopenharmony_ci	mtileb = (palign / 8) * (halign / 8) * tileb;
2728c2ecf20Sopenharmony_ci	mtile_pr = surf->nbx / palign;
2738c2ecf20Sopenharmony_ci	mtile_ps = (mtile_pr * surf->nby) / halign;
2748c2ecf20Sopenharmony_ci	surf->layer_size = mtile_ps * mtileb * slice_pt;
2758c2ecf20Sopenharmony_ci	surf->base_align = (palign / 8) * (halign / 8) * tileb;
2768c2ecf20Sopenharmony_ci	surf->palign = palign;
2778c2ecf20Sopenharmony_ci	surf->halign = halign;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	if ((surf->nbx & (palign - 1))) {
2808c2ecf20Sopenharmony_ci		if (prefix) {
2818c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d\n",
2828c2ecf20Sopenharmony_ci				 __func__, __LINE__, prefix, surf->nbx, palign);
2838c2ecf20Sopenharmony_ci		}
2848c2ecf20Sopenharmony_ci		return -EINVAL;
2858c2ecf20Sopenharmony_ci	}
2868c2ecf20Sopenharmony_ci	if ((surf->nby & (halign - 1))) {
2878c2ecf20Sopenharmony_ci		if (prefix) {
2888c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d %s height %d invalid must be aligned with %d\n",
2898c2ecf20Sopenharmony_ci				 __func__, __LINE__, prefix, surf->nby, halign);
2908c2ecf20Sopenharmony_ci		}
2918c2ecf20Sopenharmony_ci		return -EINVAL;
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	return 0;
2958c2ecf20Sopenharmony_ci}
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_cistatic int evergreen_surface_check(struct radeon_cs_parser *p,
2988c2ecf20Sopenharmony_ci				   struct eg_surface *surf,
2998c2ecf20Sopenharmony_ci				   const char *prefix)
3008c2ecf20Sopenharmony_ci{
3018c2ecf20Sopenharmony_ci	/* some common value computed here */
3028c2ecf20Sopenharmony_ci	surf->bpe = r600_fmt_get_blocksize(surf->format);
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	switch (surf->mode) {
3058c2ecf20Sopenharmony_ci	case ARRAY_LINEAR_GENERAL:
3068c2ecf20Sopenharmony_ci		return evergreen_surface_check_linear(p, surf, prefix);
3078c2ecf20Sopenharmony_ci	case ARRAY_LINEAR_ALIGNED:
3088c2ecf20Sopenharmony_ci		return evergreen_surface_check_linear_aligned(p, surf, prefix);
3098c2ecf20Sopenharmony_ci	case ARRAY_1D_TILED_THIN1:
3108c2ecf20Sopenharmony_ci		return evergreen_surface_check_1d(p, surf, prefix);
3118c2ecf20Sopenharmony_ci	case ARRAY_2D_TILED_THIN1:
3128c2ecf20Sopenharmony_ci		return evergreen_surface_check_2d(p, surf, prefix);
3138c2ecf20Sopenharmony_ci	default:
3148c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d %s invalid array mode %d\n",
3158c2ecf20Sopenharmony_ci				__func__, __LINE__, prefix, surf->mode);
3168c2ecf20Sopenharmony_ci		return -EINVAL;
3178c2ecf20Sopenharmony_ci	}
3188c2ecf20Sopenharmony_ci	return -EINVAL;
3198c2ecf20Sopenharmony_ci}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_cistatic int evergreen_surface_value_conv_check(struct radeon_cs_parser *p,
3228c2ecf20Sopenharmony_ci					      struct eg_surface *surf,
3238c2ecf20Sopenharmony_ci					      const char *prefix)
3248c2ecf20Sopenharmony_ci{
3258c2ecf20Sopenharmony_ci	switch (surf->mode) {
3268c2ecf20Sopenharmony_ci	case ARRAY_2D_TILED_THIN1:
3278c2ecf20Sopenharmony_ci		break;
3288c2ecf20Sopenharmony_ci	case ARRAY_LINEAR_GENERAL:
3298c2ecf20Sopenharmony_ci	case ARRAY_LINEAR_ALIGNED:
3308c2ecf20Sopenharmony_ci	case ARRAY_1D_TILED_THIN1:
3318c2ecf20Sopenharmony_ci		return 0;
3328c2ecf20Sopenharmony_ci	default:
3338c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d %s invalid array mode %d\n",
3348c2ecf20Sopenharmony_ci				__func__, __LINE__, prefix, surf->mode);
3358c2ecf20Sopenharmony_ci		return -EINVAL;
3368c2ecf20Sopenharmony_ci	}
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	switch (surf->nbanks) {
3398c2ecf20Sopenharmony_ci	case 0: surf->nbanks = 2; break;
3408c2ecf20Sopenharmony_ci	case 1: surf->nbanks = 4; break;
3418c2ecf20Sopenharmony_ci	case 2: surf->nbanks = 8; break;
3428c2ecf20Sopenharmony_ci	case 3: surf->nbanks = 16; break;
3438c2ecf20Sopenharmony_ci	default:
3448c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d %s invalid number of banks %d\n",
3458c2ecf20Sopenharmony_ci			 __func__, __LINE__, prefix, surf->nbanks);
3468c2ecf20Sopenharmony_ci		return -EINVAL;
3478c2ecf20Sopenharmony_ci	}
3488c2ecf20Sopenharmony_ci	switch (surf->bankw) {
3498c2ecf20Sopenharmony_ci	case 0: surf->bankw = 1; break;
3508c2ecf20Sopenharmony_ci	case 1: surf->bankw = 2; break;
3518c2ecf20Sopenharmony_ci	case 2: surf->bankw = 4; break;
3528c2ecf20Sopenharmony_ci	case 3: surf->bankw = 8; break;
3538c2ecf20Sopenharmony_ci	default:
3548c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d %s invalid bankw %d\n",
3558c2ecf20Sopenharmony_ci			 __func__, __LINE__, prefix, surf->bankw);
3568c2ecf20Sopenharmony_ci		return -EINVAL;
3578c2ecf20Sopenharmony_ci	}
3588c2ecf20Sopenharmony_ci	switch (surf->bankh) {
3598c2ecf20Sopenharmony_ci	case 0: surf->bankh = 1; break;
3608c2ecf20Sopenharmony_ci	case 1: surf->bankh = 2; break;
3618c2ecf20Sopenharmony_ci	case 2: surf->bankh = 4; break;
3628c2ecf20Sopenharmony_ci	case 3: surf->bankh = 8; break;
3638c2ecf20Sopenharmony_ci	default:
3648c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d %s invalid bankh %d\n",
3658c2ecf20Sopenharmony_ci			 __func__, __LINE__, prefix, surf->bankh);
3668c2ecf20Sopenharmony_ci		return -EINVAL;
3678c2ecf20Sopenharmony_ci	}
3688c2ecf20Sopenharmony_ci	switch (surf->mtilea) {
3698c2ecf20Sopenharmony_ci	case 0: surf->mtilea = 1; break;
3708c2ecf20Sopenharmony_ci	case 1: surf->mtilea = 2; break;
3718c2ecf20Sopenharmony_ci	case 2: surf->mtilea = 4; break;
3728c2ecf20Sopenharmony_ci	case 3: surf->mtilea = 8; break;
3738c2ecf20Sopenharmony_ci	default:
3748c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d %s invalid macro tile aspect %d\n",
3758c2ecf20Sopenharmony_ci			 __func__, __LINE__, prefix, surf->mtilea);
3768c2ecf20Sopenharmony_ci		return -EINVAL;
3778c2ecf20Sopenharmony_ci	}
3788c2ecf20Sopenharmony_ci	switch (surf->tsplit) {
3798c2ecf20Sopenharmony_ci	case 0: surf->tsplit = 64; break;
3808c2ecf20Sopenharmony_ci	case 1: surf->tsplit = 128; break;
3818c2ecf20Sopenharmony_ci	case 2: surf->tsplit = 256; break;
3828c2ecf20Sopenharmony_ci	case 3: surf->tsplit = 512; break;
3838c2ecf20Sopenharmony_ci	case 4: surf->tsplit = 1024; break;
3848c2ecf20Sopenharmony_ci	case 5: surf->tsplit = 2048; break;
3858c2ecf20Sopenharmony_ci	case 6: surf->tsplit = 4096; break;
3868c2ecf20Sopenharmony_ci	default:
3878c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d %s invalid tile split %d\n",
3888c2ecf20Sopenharmony_ci			 __func__, __LINE__, prefix, surf->tsplit);
3898c2ecf20Sopenharmony_ci		return -EINVAL;
3908c2ecf20Sopenharmony_ci	}
3918c2ecf20Sopenharmony_ci	return 0;
3928c2ecf20Sopenharmony_ci}
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_cistatic int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned id)
3958c2ecf20Sopenharmony_ci{
3968c2ecf20Sopenharmony_ci	struct evergreen_cs_track *track = p->track;
3978c2ecf20Sopenharmony_ci	struct eg_surface surf;
3988c2ecf20Sopenharmony_ci	unsigned pitch, slice, mslice;
3998c2ecf20Sopenharmony_ci	unsigned long offset;
4008c2ecf20Sopenharmony_ci	int r;
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	mslice = G_028C6C_SLICE_MAX(track->cb_color_view[id]) + 1;
4038c2ecf20Sopenharmony_ci	pitch = track->cb_color_pitch[id];
4048c2ecf20Sopenharmony_ci	slice = track->cb_color_slice[id];
4058c2ecf20Sopenharmony_ci	surf.nbx = (pitch + 1) * 8;
4068c2ecf20Sopenharmony_ci	surf.nby = ((slice + 1) * 64) / surf.nbx;
4078c2ecf20Sopenharmony_ci	surf.mode = G_028C70_ARRAY_MODE(track->cb_color_info[id]);
4088c2ecf20Sopenharmony_ci	surf.format = G_028C70_FORMAT(track->cb_color_info[id]);
4098c2ecf20Sopenharmony_ci	surf.tsplit = G_028C74_TILE_SPLIT(track->cb_color_attrib[id]);
4108c2ecf20Sopenharmony_ci	surf.nbanks = G_028C74_NUM_BANKS(track->cb_color_attrib[id]);
4118c2ecf20Sopenharmony_ci	surf.bankw = G_028C74_BANK_WIDTH(track->cb_color_attrib[id]);
4128c2ecf20Sopenharmony_ci	surf.bankh = G_028C74_BANK_HEIGHT(track->cb_color_attrib[id]);
4138c2ecf20Sopenharmony_ci	surf.mtilea = G_028C74_MACRO_TILE_ASPECT(track->cb_color_attrib[id]);
4148c2ecf20Sopenharmony_ci	surf.nsamples = 1;
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	if (!r600_fmt_is_valid_color(surf.format)) {
4178c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08x)\n",
4188c2ecf20Sopenharmony_ci			 __func__, __LINE__, surf.format,
4198c2ecf20Sopenharmony_ci			id, track->cb_color_info[id]);
4208c2ecf20Sopenharmony_ci		return -EINVAL;
4218c2ecf20Sopenharmony_ci	}
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	r = evergreen_surface_value_conv_check(p, &surf, "cb");
4248c2ecf20Sopenharmony_ci	if (r) {
4258c2ecf20Sopenharmony_ci		return r;
4268c2ecf20Sopenharmony_ci	}
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	r = evergreen_surface_check(p, &surf, "cb");
4298c2ecf20Sopenharmony_ci	if (r) {
4308c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d cb[%d] invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n",
4318c2ecf20Sopenharmony_ci			 __func__, __LINE__, id, track->cb_color_pitch[id],
4328c2ecf20Sopenharmony_ci			 track->cb_color_slice[id], track->cb_color_attrib[id],
4338c2ecf20Sopenharmony_ci			 track->cb_color_info[id]);
4348c2ecf20Sopenharmony_ci		return r;
4358c2ecf20Sopenharmony_ci	}
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	offset = track->cb_color_bo_offset[id] << 8;
4388c2ecf20Sopenharmony_ci	if (offset & (surf.base_align - 1)) {
4398c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d cb[%d] bo base %ld not aligned with %ld\n",
4408c2ecf20Sopenharmony_ci			 __func__, __LINE__, id, offset, surf.base_align);
4418c2ecf20Sopenharmony_ci		return -EINVAL;
4428c2ecf20Sopenharmony_ci	}
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	offset += surf.layer_size * mslice;
4458c2ecf20Sopenharmony_ci	if (offset > radeon_bo_size(track->cb_color_bo[id])) {
4468c2ecf20Sopenharmony_ci		/* old ddx are broken they allocate bo with w*h*bpp but
4478c2ecf20Sopenharmony_ci		 * program slice with ALIGN(h, 8), catch this and patch
4488c2ecf20Sopenharmony_ci		 * command stream.
4498c2ecf20Sopenharmony_ci		 */
4508c2ecf20Sopenharmony_ci		if (!surf.mode) {
4518c2ecf20Sopenharmony_ci			uint32_t *ib = p->ib.ptr;
4528c2ecf20Sopenharmony_ci			unsigned long tmp, nby, bsize, size, min = 0;
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci			/* find the height the ddx wants */
4558c2ecf20Sopenharmony_ci			if (surf.nby > 8) {
4568c2ecf20Sopenharmony_ci				min = surf.nby - 8;
4578c2ecf20Sopenharmony_ci			}
4588c2ecf20Sopenharmony_ci			bsize = radeon_bo_size(track->cb_color_bo[id]);
4598c2ecf20Sopenharmony_ci			tmp = track->cb_color_bo_offset[id] << 8;
4608c2ecf20Sopenharmony_ci			for (nby = surf.nby; nby > min; nby--) {
4618c2ecf20Sopenharmony_ci				size = nby * surf.nbx * surf.bpe * surf.nsamples;
4628c2ecf20Sopenharmony_ci				if ((tmp + size * mslice) <= bsize) {
4638c2ecf20Sopenharmony_ci					break;
4648c2ecf20Sopenharmony_ci				}
4658c2ecf20Sopenharmony_ci			}
4668c2ecf20Sopenharmony_ci			if (nby > min) {
4678c2ecf20Sopenharmony_ci				surf.nby = nby;
4688c2ecf20Sopenharmony_ci				slice = ((nby * surf.nbx) / 64) - 1;
4698c2ecf20Sopenharmony_ci				if (!evergreen_surface_check(p, &surf, "cb")) {
4708c2ecf20Sopenharmony_ci					/* check if this one works */
4718c2ecf20Sopenharmony_ci					tmp += surf.layer_size * mslice;
4728c2ecf20Sopenharmony_ci					if (tmp <= bsize) {
4738c2ecf20Sopenharmony_ci						ib[track->cb_color_slice_idx[id]] = slice;
4748c2ecf20Sopenharmony_ci						goto old_ddx_ok;
4758c2ecf20Sopenharmony_ci					}
4768c2ecf20Sopenharmony_ci				}
4778c2ecf20Sopenharmony_ci			}
4788c2ecf20Sopenharmony_ci		}
4798c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, "
4808c2ecf20Sopenharmony_ci			 "offset %d, max layer %d, bo size %ld, slice %d)\n",
4818c2ecf20Sopenharmony_ci			 __func__, __LINE__, id, surf.layer_size,
4828c2ecf20Sopenharmony_ci			track->cb_color_bo_offset[id] << 8, mslice,
4838c2ecf20Sopenharmony_ci			radeon_bo_size(track->cb_color_bo[id]), slice);
4848c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n",
4858c2ecf20Sopenharmony_ci			 __func__, __LINE__, surf.nbx, surf.nby,
4868c2ecf20Sopenharmony_ci			surf.mode, surf.bpe, surf.nsamples,
4878c2ecf20Sopenharmony_ci			surf.bankw, surf.bankh,
4888c2ecf20Sopenharmony_ci			surf.tsplit, surf.mtilea);
4898c2ecf20Sopenharmony_ci		return -EINVAL;
4908c2ecf20Sopenharmony_ci	}
4918c2ecf20Sopenharmony_ciold_ddx_ok:
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	return 0;
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_cistatic int evergreen_cs_track_validate_htile(struct radeon_cs_parser *p,
4978c2ecf20Sopenharmony_ci						unsigned nbx, unsigned nby)
4988c2ecf20Sopenharmony_ci{
4998c2ecf20Sopenharmony_ci	struct evergreen_cs_track *track = p->track;
5008c2ecf20Sopenharmony_ci	unsigned long size;
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	if (track->htile_bo == NULL) {
5038c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n",
5048c2ecf20Sopenharmony_ci				__func__, __LINE__, track->db_z_info);
5058c2ecf20Sopenharmony_ci		return -EINVAL;
5068c2ecf20Sopenharmony_ci	}
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	if (G_028ABC_LINEAR(track->htile_surface)) {
5098c2ecf20Sopenharmony_ci		/* pitch must be 16 htiles aligned == 16 * 8 pixel aligned */
5108c2ecf20Sopenharmony_ci		nbx = round_up(nbx, 16 * 8);
5118c2ecf20Sopenharmony_ci		/* height is npipes htiles aligned == npipes * 8 pixel aligned */
5128c2ecf20Sopenharmony_ci		nby = round_up(nby, track->npipes * 8);
5138c2ecf20Sopenharmony_ci	} else {
5148c2ecf20Sopenharmony_ci		/* always assume 8x8 htile */
5158c2ecf20Sopenharmony_ci		/* align is htile align * 8, htile align vary according to
5168c2ecf20Sopenharmony_ci		 * number of pipe and tile width and nby
5178c2ecf20Sopenharmony_ci		 */
5188c2ecf20Sopenharmony_ci		switch (track->npipes) {
5198c2ecf20Sopenharmony_ci		case 8:
5208c2ecf20Sopenharmony_ci			/* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
5218c2ecf20Sopenharmony_ci			nbx = round_up(nbx, 64 * 8);
5228c2ecf20Sopenharmony_ci			nby = round_up(nby, 64 * 8);
5238c2ecf20Sopenharmony_ci			break;
5248c2ecf20Sopenharmony_ci		case 4:
5258c2ecf20Sopenharmony_ci			/* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
5268c2ecf20Sopenharmony_ci			nbx = round_up(nbx, 64 * 8);
5278c2ecf20Sopenharmony_ci			nby = round_up(nby, 32 * 8);
5288c2ecf20Sopenharmony_ci			break;
5298c2ecf20Sopenharmony_ci		case 2:
5308c2ecf20Sopenharmony_ci			/* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
5318c2ecf20Sopenharmony_ci			nbx = round_up(nbx, 32 * 8);
5328c2ecf20Sopenharmony_ci			nby = round_up(nby, 32 * 8);
5338c2ecf20Sopenharmony_ci			break;
5348c2ecf20Sopenharmony_ci		case 1:
5358c2ecf20Sopenharmony_ci			/* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
5368c2ecf20Sopenharmony_ci			nbx = round_up(nbx, 32 * 8);
5378c2ecf20Sopenharmony_ci			nby = round_up(nby, 16 * 8);
5388c2ecf20Sopenharmony_ci			break;
5398c2ecf20Sopenharmony_ci		default:
5408c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d invalid num pipes %d\n",
5418c2ecf20Sopenharmony_ci					__func__, __LINE__, track->npipes);
5428c2ecf20Sopenharmony_ci			return -EINVAL;
5438c2ecf20Sopenharmony_ci		}
5448c2ecf20Sopenharmony_ci	}
5458c2ecf20Sopenharmony_ci	/* compute number of htile */
5468c2ecf20Sopenharmony_ci	nbx = nbx >> 3;
5478c2ecf20Sopenharmony_ci	nby = nby >> 3;
5488c2ecf20Sopenharmony_ci	/* size must be aligned on npipes * 2K boundary */
5498c2ecf20Sopenharmony_ci	size = roundup(nbx * nby * 4, track->npipes * (2 << 10));
5508c2ecf20Sopenharmony_ci	size += track->htile_offset;
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	if (size > radeon_bo_size(track->htile_bo)) {
5538c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n",
5548c2ecf20Sopenharmony_ci				__func__, __LINE__, radeon_bo_size(track->htile_bo),
5558c2ecf20Sopenharmony_ci				size, nbx, nby);
5568c2ecf20Sopenharmony_ci		return -EINVAL;
5578c2ecf20Sopenharmony_ci	}
5588c2ecf20Sopenharmony_ci	return 0;
5598c2ecf20Sopenharmony_ci}
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_cistatic int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p)
5628c2ecf20Sopenharmony_ci{
5638c2ecf20Sopenharmony_ci	struct evergreen_cs_track *track = p->track;
5648c2ecf20Sopenharmony_ci	struct eg_surface surf;
5658c2ecf20Sopenharmony_ci	unsigned pitch, slice, mslice;
5668c2ecf20Sopenharmony_ci	unsigned long offset;
5678c2ecf20Sopenharmony_ci	int r;
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1;
5708c2ecf20Sopenharmony_ci	pitch = G_028058_PITCH_TILE_MAX(track->db_depth_size);
5718c2ecf20Sopenharmony_ci	slice = track->db_depth_slice;
5728c2ecf20Sopenharmony_ci	surf.nbx = (pitch + 1) * 8;
5738c2ecf20Sopenharmony_ci	surf.nby = ((slice + 1) * 64) / surf.nbx;
5748c2ecf20Sopenharmony_ci	surf.mode = G_028040_ARRAY_MODE(track->db_z_info);
5758c2ecf20Sopenharmony_ci	surf.format = G_028044_FORMAT(track->db_s_info);
5768c2ecf20Sopenharmony_ci	surf.tsplit = G_028044_TILE_SPLIT(track->db_s_info);
5778c2ecf20Sopenharmony_ci	surf.nbanks = G_028040_NUM_BANKS(track->db_z_info);
5788c2ecf20Sopenharmony_ci	surf.bankw = G_028040_BANK_WIDTH(track->db_z_info);
5798c2ecf20Sopenharmony_ci	surf.bankh = G_028040_BANK_HEIGHT(track->db_z_info);
5808c2ecf20Sopenharmony_ci	surf.mtilea = G_028040_MACRO_TILE_ASPECT(track->db_z_info);
5818c2ecf20Sopenharmony_ci	surf.nsamples = 1;
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	if (surf.format != 1) {
5848c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d stencil invalid format %d\n",
5858c2ecf20Sopenharmony_ci			 __func__, __LINE__, surf.format);
5868c2ecf20Sopenharmony_ci		return -EINVAL;
5878c2ecf20Sopenharmony_ci	}
5888c2ecf20Sopenharmony_ci	/* replace by color format so we can use same code */
5898c2ecf20Sopenharmony_ci	surf.format = V_028C70_COLOR_8;
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	r = evergreen_surface_value_conv_check(p, &surf, "stencil");
5928c2ecf20Sopenharmony_ci	if (r) {
5938c2ecf20Sopenharmony_ci		return r;
5948c2ecf20Sopenharmony_ci	}
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	r = evergreen_surface_check(p, &surf, NULL);
5978c2ecf20Sopenharmony_ci	if (r) {
5988c2ecf20Sopenharmony_ci		/* old userspace doesn't compute proper depth/stencil alignment
5998c2ecf20Sopenharmony_ci		 * check that alignment against a bigger byte per elements and
6008c2ecf20Sopenharmony_ci		 * only report if that alignment is wrong too.
6018c2ecf20Sopenharmony_ci		 */
6028c2ecf20Sopenharmony_ci		surf.format = V_028C70_COLOR_8_8_8_8;
6038c2ecf20Sopenharmony_ci		r = evergreen_surface_check(p, &surf, "stencil");
6048c2ecf20Sopenharmony_ci		if (r) {
6058c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n",
6068c2ecf20Sopenharmony_ci				 __func__, __LINE__, track->db_depth_size,
6078c2ecf20Sopenharmony_ci				 track->db_depth_slice, track->db_s_info, track->db_z_info);
6088c2ecf20Sopenharmony_ci		}
6098c2ecf20Sopenharmony_ci		return r;
6108c2ecf20Sopenharmony_ci	}
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	offset = track->db_s_read_offset << 8;
6138c2ecf20Sopenharmony_ci	if (offset & (surf.base_align - 1)) {
6148c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n",
6158c2ecf20Sopenharmony_ci			 __func__, __LINE__, offset, surf.base_align);
6168c2ecf20Sopenharmony_ci		return -EINVAL;
6178c2ecf20Sopenharmony_ci	}
6188c2ecf20Sopenharmony_ci	offset += surf.layer_size * mslice;
6198c2ecf20Sopenharmony_ci	if (offset > radeon_bo_size(track->db_s_read_bo)) {
6208c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d stencil read bo too small (layer size %d, "
6218c2ecf20Sopenharmony_ci			 "offset %ld, max layer %d, bo size %ld)\n",
6228c2ecf20Sopenharmony_ci			 __func__, __LINE__, surf.layer_size,
6238c2ecf20Sopenharmony_ci			(unsigned long)track->db_s_read_offset << 8, mslice,
6248c2ecf20Sopenharmony_ci			radeon_bo_size(track->db_s_read_bo));
6258c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n",
6268c2ecf20Sopenharmony_ci			 __func__, __LINE__, track->db_depth_size,
6278c2ecf20Sopenharmony_ci			 track->db_depth_slice, track->db_s_info, track->db_z_info);
6288c2ecf20Sopenharmony_ci		return -EINVAL;
6298c2ecf20Sopenharmony_ci	}
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci	offset = track->db_s_write_offset << 8;
6328c2ecf20Sopenharmony_ci	if (offset & (surf.base_align - 1)) {
6338c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n",
6348c2ecf20Sopenharmony_ci			 __func__, __LINE__, offset, surf.base_align);
6358c2ecf20Sopenharmony_ci		return -EINVAL;
6368c2ecf20Sopenharmony_ci	}
6378c2ecf20Sopenharmony_ci	offset += surf.layer_size * mslice;
6388c2ecf20Sopenharmony_ci	if (offset > radeon_bo_size(track->db_s_write_bo)) {
6398c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d stencil write bo too small (layer size %d, "
6408c2ecf20Sopenharmony_ci			 "offset %ld, max layer %d, bo size %ld)\n",
6418c2ecf20Sopenharmony_ci			 __func__, __LINE__, surf.layer_size,
6428c2ecf20Sopenharmony_ci			(unsigned long)track->db_s_write_offset << 8, mslice,
6438c2ecf20Sopenharmony_ci			radeon_bo_size(track->db_s_write_bo));
6448c2ecf20Sopenharmony_ci		return -EINVAL;
6458c2ecf20Sopenharmony_ci	}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	/* hyperz */
6488c2ecf20Sopenharmony_ci	if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) {
6498c2ecf20Sopenharmony_ci		r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby);
6508c2ecf20Sopenharmony_ci		if (r) {
6518c2ecf20Sopenharmony_ci			return r;
6528c2ecf20Sopenharmony_ci		}
6538c2ecf20Sopenharmony_ci	}
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	return 0;
6568c2ecf20Sopenharmony_ci}
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_cistatic int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p)
6598c2ecf20Sopenharmony_ci{
6608c2ecf20Sopenharmony_ci	struct evergreen_cs_track *track = p->track;
6618c2ecf20Sopenharmony_ci	struct eg_surface surf;
6628c2ecf20Sopenharmony_ci	unsigned pitch, slice, mslice;
6638c2ecf20Sopenharmony_ci	unsigned long offset;
6648c2ecf20Sopenharmony_ci	int r;
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1;
6678c2ecf20Sopenharmony_ci	pitch = G_028058_PITCH_TILE_MAX(track->db_depth_size);
6688c2ecf20Sopenharmony_ci	slice = track->db_depth_slice;
6698c2ecf20Sopenharmony_ci	surf.nbx = (pitch + 1) * 8;
6708c2ecf20Sopenharmony_ci	surf.nby = ((slice + 1) * 64) / surf.nbx;
6718c2ecf20Sopenharmony_ci	surf.mode = G_028040_ARRAY_MODE(track->db_z_info);
6728c2ecf20Sopenharmony_ci	surf.format = G_028040_FORMAT(track->db_z_info);
6738c2ecf20Sopenharmony_ci	surf.tsplit = G_028040_TILE_SPLIT(track->db_z_info);
6748c2ecf20Sopenharmony_ci	surf.nbanks = G_028040_NUM_BANKS(track->db_z_info);
6758c2ecf20Sopenharmony_ci	surf.bankw = G_028040_BANK_WIDTH(track->db_z_info);
6768c2ecf20Sopenharmony_ci	surf.bankh = G_028040_BANK_HEIGHT(track->db_z_info);
6778c2ecf20Sopenharmony_ci	surf.mtilea = G_028040_MACRO_TILE_ASPECT(track->db_z_info);
6788c2ecf20Sopenharmony_ci	surf.nsamples = 1;
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	switch (surf.format) {
6818c2ecf20Sopenharmony_ci	case V_028040_Z_16:
6828c2ecf20Sopenharmony_ci		surf.format = V_028C70_COLOR_16;
6838c2ecf20Sopenharmony_ci		break;
6848c2ecf20Sopenharmony_ci	case V_028040_Z_24:
6858c2ecf20Sopenharmony_ci	case V_028040_Z_32_FLOAT:
6868c2ecf20Sopenharmony_ci		surf.format = V_028C70_COLOR_8_8_8_8;
6878c2ecf20Sopenharmony_ci		break;
6888c2ecf20Sopenharmony_ci	default:
6898c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d depth invalid format %d\n",
6908c2ecf20Sopenharmony_ci			 __func__, __LINE__, surf.format);
6918c2ecf20Sopenharmony_ci		return -EINVAL;
6928c2ecf20Sopenharmony_ci	}
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	r = evergreen_surface_value_conv_check(p, &surf, "depth");
6958c2ecf20Sopenharmony_ci	if (r) {
6968c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d depth invalid (0x%08x 0x%08x 0x%08x)\n",
6978c2ecf20Sopenharmony_ci			 __func__, __LINE__, track->db_depth_size,
6988c2ecf20Sopenharmony_ci			 track->db_depth_slice, track->db_z_info);
6998c2ecf20Sopenharmony_ci		return r;
7008c2ecf20Sopenharmony_ci	}
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	r = evergreen_surface_check(p, &surf, "depth");
7038c2ecf20Sopenharmony_ci	if (r) {
7048c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d depth invalid (0x%08x 0x%08x 0x%08x)\n",
7058c2ecf20Sopenharmony_ci			 __func__, __LINE__, track->db_depth_size,
7068c2ecf20Sopenharmony_ci			 track->db_depth_slice, track->db_z_info);
7078c2ecf20Sopenharmony_ci		return r;
7088c2ecf20Sopenharmony_ci	}
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	offset = track->db_z_read_offset << 8;
7118c2ecf20Sopenharmony_ci	if (offset & (surf.base_align - 1)) {
7128c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n",
7138c2ecf20Sopenharmony_ci			 __func__, __LINE__, offset, surf.base_align);
7148c2ecf20Sopenharmony_ci		return -EINVAL;
7158c2ecf20Sopenharmony_ci	}
7168c2ecf20Sopenharmony_ci	offset += surf.layer_size * mslice;
7178c2ecf20Sopenharmony_ci	if (offset > radeon_bo_size(track->db_z_read_bo)) {
7188c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d depth read bo too small (layer size %d, "
7198c2ecf20Sopenharmony_ci			 "offset %ld, max layer %d, bo size %ld)\n",
7208c2ecf20Sopenharmony_ci			 __func__, __LINE__, surf.layer_size,
7218c2ecf20Sopenharmony_ci			(unsigned long)track->db_z_read_offset << 8, mslice,
7228c2ecf20Sopenharmony_ci			radeon_bo_size(track->db_z_read_bo));
7238c2ecf20Sopenharmony_ci		return -EINVAL;
7248c2ecf20Sopenharmony_ci	}
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	offset = track->db_z_write_offset << 8;
7278c2ecf20Sopenharmony_ci	if (offset & (surf.base_align - 1)) {
7288c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n",
7298c2ecf20Sopenharmony_ci			 __func__, __LINE__, offset, surf.base_align);
7308c2ecf20Sopenharmony_ci		return -EINVAL;
7318c2ecf20Sopenharmony_ci	}
7328c2ecf20Sopenharmony_ci	offset += surf.layer_size * mslice;
7338c2ecf20Sopenharmony_ci	if (offset > radeon_bo_size(track->db_z_write_bo)) {
7348c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d depth write bo too small (layer size %d, "
7358c2ecf20Sopenharmony_ci			 "offset %ld, max layer %d, bo size %ld)\n",
7368c2ecf20Sopenharmony_ci			 __func__, __LINE__, surf.layer_size,
7378c2ecf20Sopenharmony_ci			(unsigned long)track->db_z_write_offset << 8, mslice,
7388c2ecf20Sopenharmony_ci			radeon_bo_size(track->db_z_write_bo));
7398c2ecf20Sopenharmony_ci		return -EINVAL;
7408c2ecf20Sopenharmony_ci	}
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci	/* hyperz */
7438c2ecf20Sopenharmony_ci	if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) {
7448c2ecf20Sopenharmony_ci		r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby);
7458c2ecf20Sopenharmony_ci		if (r) {
7468c2ecf20Sopenharmony_ci			return r;
7478c2ecf20Sopenharmony_ci		}
7488c2ecf20Sopenharmony_ci	}
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	return 0;
7518c2ecf20Sopenharmony_ci}
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_cistatic int evergreen_cs_track_validate_texture(struct radeon_cs_parser *p,
7548c2ecf20Sopenharmony_ci					       struct radeon_bo *texture,
7558c2ecf20Sopenharmony_ci					       struct radeon_bo *mipmap,
7568c2ecf20Sopenharmony_ci					       unsigned idx)
7578c2ecf20Sopenharmony_ci{
7588c2ecf20Sopenharmony_ci	struct eg_surface surf;
7598c2ecf20Sopenharmony_ci	unsigned long toffset, moffset;
7608c2ecf20Sopenharmony_ci	unsigned dim, llevel, mslice, width, height, depth, i;
7618c2ecf20Sopenharmony_ci	u32 texdw[8];
7628c2ecf20Sopenharmony_ci	int r;
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	texdw[0] = radeon_get_ib_value(p, idx + 0);
7658c2ecf20Sopenharmony_ci	texdw[1] = radeon_get_ib_value(p, idx + 1);
7668c2ecf20Sopenharmony_ci	texdw[2] = radeon_get_ib_value(p, idx + 2);
7678c2ecf20Sopenharmony_ci	texdw[3] = radeon_get_ib_value(p, idx + 3);
7688c2ecf20Sopenharmony_ci	texdw[4] = radeon_get_ib_value(p, idx + 4);
7698c2ecf20Sopenharmony_ci	texdw[5] = radeon_get_ib_value(p, idx + 5);
7708c2ecf20Sopenharmony_ci	texdw[6] = radeon_get_ib_value(p, idx + 6);
7718c2ecf20Sopenharmony_ci	texdw[7] = radeon_get_ib_value(p, idx + 7);
7728c2ecf20Sopenharmony_ci	dim = G_030000_DIM(texdw[0]);
7738c2ecf20Sopenharmony_ci	llevel = G_030014_LAST_LEVEL(texdw[5]);
7748c2ecf20Sopenharmony_ci	mslice = G_030014_LAST_ARRAY(texdw[5]) + 1;
7758c2ecf20Sopenharmony_ci	width = G_030000_TEX_WIDTH(texdw[0]) + 1;
7768c2ecf20Sopenharmony_ci	height =  G_030004_TEX_HEIGHT(texdw[1]) + 1;
7778c2ecf20Sopenharmony_ci	depth = G_030004_TEX_DEPTH(texdw[1]) + 1;
7788c2ecf20Sopenharmony_ci	surf.format = G_03001C_DATA_FORMAT(texdw[7]);
7798c2ecf20Sopenharmony_ci	surf.nbx = (G_030000_PITCH(texdw[0]) + 1) * 8;
7808c2ecf20Sopenharmony_ci	surf.nbx = r600_fmt_get_nblocksx(surf.format, surf.nbx);
7818c2ecf20Sopenharmony_ci	surf.nby = r600_fmt_get_nblocksy(surf.format, height);
7828c2ecf20Sopenharmony_ci	surf.mode = G_030004_ARRAY_MODE(texdw[1]);
7838c2ecf20Sopenharmony_ci	surf.tsplit = G_030018_TILE_SPLIT(texdw[6]);
7848c2ecf20Sopenharmony_ci	surf.nbanks = G_03001C_NUM_BANKS(texdw[7]);
7858c2ecf20Sopenharmony_ci	surf.bankw = G_03001C_BANK_WIDTH(texdw[7]);
7868c2ecf20Sopenharmony_ci	surf.bankh = G_03001C_BANK_HEIGHT(texdw[7]);
7878c2ecf20Sopenharmony_ci	surf.mtilea = G_03001C_MACRO_TILE_ASPECT(texdw[7]);
7888c2ecf20Sopenharmony_ci	surf.nsamples = 1;
7898c2ecf20Sopenharmony_ci	toffset = texdw[2] << 8;
7908c2ecf20Sopenharmony_ci	moffset = texdw[3] << 8;
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	if (!r600_fmt_is_valid_texture(surf.format, p->family)) {
7938c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d texture invalid format %d\n",
7948c2ecf20Sopenharmony_ci			 __func__, __LINE__, surf.format);
7958c2ecf20Sopenharmony_ci		return -EINVAL;
7968c2ecf20Sopenharmony_ci	}
7978c2ecf20Sopenharmony_ci	switch (dim) {
7988c2ecf20Sopenharmony_ci	case V_030000_SQ_TEX_DIM_1D:
7998c2ecf20Sopenharmony_ci	case V_030000_SQ_TEX_DIM_2D:
8008c2ecf20Sopenharmony_ci	case V_030000_SQ_TEX_DIM_CUBEMAP:
8018c2ecf20Sopenharmony_ci	case V_030000_SQ_TEX_DIM_1D_ARRAY:
8028c2ecf20Sopenharmony_ci	case V_030000_SQ_TEX_DIM_2D_ARRAY:
8038c2ecf20Sopenharmony_ci		depth = 1;
8048c2ecf20Sopenharmony_ci		break;
8058c2ecf20Sopenharmony_ci	case V_030000_SQ_TEX_DIM_2D_MSAA:
8068c2ecf20Sopenharmony_ci	case V_030000_SQ_TEX_DIM_2D_ARRAY_MSAA:
8078c2ecf20Sopenharmony_ci		surf.nsamples = 1 << llevel;
8088c2ecf20Sopenharmony_ci		llevel = 0;
8098c2ecf20Sopenharmony_ci		depth = 1;
8108c2ecf20Sopenharmony_ci		break;
8118c2ecf20Sopenharmony_ci	case V_030000_SQ_TEX_DIM_3D:
8128c2ecf20Sopenharmony_ci		break;
8138c2ecf20Sopenharmony_ci	default:
8148c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d texture invalid dimension %d\n",
8158c2ecf20Sopenharmony_ci			 __func__, __LINE__, dim);
8168c2ecf20Sopenharmony_ci		return -EINVAL;
8178c2ecf20Sopenharmony_ci	}
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	r = evergreen_surface_value_conv_check(p, &surf, "texture");
8208c2ecf20Sopenharmony_ci	if (r) {
8218c2ecf20Sopenharmony_ci		return r;
8228c2ecf20Sopenharmony_ci	}
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	/* align height */
8258c2ecf20Sopenharmony_ci	evergreen_surface_check(p, &surf, NULL);
8268c2ecf20Sopenharmony_ci	surf.nby = ALIGN(surf.nby, surf.halign);
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci	r = evergreen_surface_check(p, &surf, "texture");
8298c2ecf20Sopenharmony_ci	if (r) {
8308c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d texture invalid 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
8318c2ecf20Sopenharmony_ci			 __func__, __LINE__, texdw[0], texdw[1], texdw[4],
8328c2ecf20Sopenharmony_ci			 texdw[5], texdw[6], texdw[7]);
8338c2ecf20Sopenharmony_ci		return r;
8348c2ecf20Sopenharmony_ci	}
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	/* check texture size */
8378c2ecf20Sopenharmony_ci	if (toffset & (surf.base_align - 1)) {
8388c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d texture bo base %ld not aligned with %ld\n",
8398c2ecf20Sopenharmony_ci			 __func__, __LINE__, toffset, surf.base_align);
8408c2ecf20Sopenharmony_ci		return -EINVAL;
8418c2ecf20Sopenharmony_ci	}
8428c2ecf20Sopenharmony_ci	if (surf.nsamples <= 1 && moffset & (surf.base_align - 1)) {
8438c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d mipmap bo base %ld not aligned with %ld\n",
8448c2ecf20Sopenharmony_ci			 __func__, __LINE__, moffset, surf.base_align);
8458c2ecf20Sopenharmony_ci		return -EINVAL;
8468c2ecf20Sopenharmony_ci	}
8478c2ecf20Sopenharmony_ci	if (dim == SQ_TEX_DIM_3D) {
8488c2ecf20Sopenharmony_ci		toffset += surf.layer_size * depth;
8498c2ecf20Sopenharmony_ci	} else {
8508c2ecf20Sopenharmony_ci		toffset += surf.layer_size * mslice;
8518c2ecf20Sopenharmony_ci	}
8528c2ecf20Sopenharmony_ci	if (toffset > radeon_bo_size(texture)) {
8538c2ecf20Sopenharmony_ci		dev_warn(p->dev, "%s:%d texture bo too small (layer size %d, "
8548c2ecf20Sopenharmony_ci			 "offset %ld, max layer %d, depth %d, bo size %ld) (%d %d)\n",
8558c2ecf20Sopenharmony_ci			 __func__, __LINE__, surf.layer_size,
8568c2ecf20Sopenharmony_ci			(unsigned long)texdw[2] << 8, mslice,
8578c2ecf20Sopenharmony_ci			depth, radeon_bo_size(texture),
8588c2ecf20Sopenharmony_ci			surf.nbx, surf.nby);
8598c2ecf20Sopenharmony_ci		return -EINVAL;
8608c2ecf20Sopenharmony_ci	}
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ci	if (!mipmap) {
8638c2ecf20Sopenharmony_ci		if (llevel) {
8648c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%i got NULL MIP_ADDRESS relocation\n",
8658c2ecf20Sopenharmony_ci				 __func__, __LINE__);
8668c2ecf20Sopenharmony_ci			return -EINVAL;
8678c2ecf20Sopenharmony_ci		} else {
8688c2ecf20Sopenharmony_ci			return 0; /* everything's ok */
8698c2ecf20Sopenharmony_ci		}
8708c2ecf20Sopenharmony_ci	}
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	/* check mipmap size */
8738c2ecf20Sopenharmony_ci	for (i = 1; i <= llevel; i++) {
8748c2ecf20Sopenharmony_ci		unsigned w, h, d;
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ci		w = r600_mip_minify(width, i);
8778c2ecf20Sopenharmony_ci		h = r600_mip_minify(height, i);
8788c2ecf20Sopenharmony_ci		d = r600_mip_minify(depth, i);
8798c2ecf20Sopenharmony_ci		surf.nbx = r600_fmt_get_nblocksx(surf.format, w);
8808c2ecf20Sopenharmony_ci		surf.nby = r600_fmt_get_nblocksy(surf.format, h);
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci		switch (surf.mode) {
8838c2ecf20Sopenharmony_ci		case ARRAY_2D_TILED_THIN1:
8848c2ecf20Sopenharmony_ci			if (surf.nbx < surf.palign || surf.nby < surf.halign) {
8858c2ecf20Sopenharmony_ci				surf.mode = ARRAY_1D_TILED_THIN1;
8868c2ecf20Sopenharmony_ci			}
8878c2ecf20Sopenharmony_ci			/* recompute alignment */
8888c2ecf20Sopenharmony_ci			evergreen_surface_check(p, &surf, NULL);
8898c2ecf20Sopenharmony_ci			break;
8908c2ecf20Sopenharmony_ci		case ARRAY_LINEAR_GENERAL:
8918c2ecf20Sopenharmony_ci		case ARRAY_LINEAR_ALIGNED:
8928c2ecf20Sopenharmony_ci		case ARRAY_1D_TILED_THIN1:
8938c2ecf20Sopenharmony_ci			break;
8948c2ecf20Sopenharmony_ci		default:
8958c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d invalid array mode %d\n",
8968c2ecf20Sopenharmony_ci				 __func__, __LINE__, surf.mode);
8978c2ecf20Sopenharmony_ci			return -EINVAL;
8988c2ecf20Sopenharmony_ci		}
8998c2ecf20Sopenharmony_ci		surf.nbx = ALIGN(surf.nbx, surf.palign);
9008c2ecf20Sopenharmony_ci		surf.nby = ALIGN(surf.nby, surf.halign);
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci		r = evergreen_surface_check(p, &surf, "mipmap");
9038c2ecf20Sopenharmony_ci		if (r) {
9048c2ecf20Sopenharmony_ci			return r;
9058c2ecf20Sopenharmony_ci		}
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci		if (dim == SQ_TEX_DIM_3D) {
9088c2ecf20Sopenharmony_ci			moffset += surf.layer_size * d;
9098c2ecf20Sopenharmony_ci		} else {
9108c2ecf20Sopenharmony_ci			moffset += surf.layer_size * mslice;
9118c2ecf20Sopenharmony_ci		}
9128c2ecf20Sopenharmony_ci		if (moffset > radeon_bo_size(mipmap)) {
9138c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d mipmap [%d] bo too small (layer size %d, "
9148c2ecf20Sopenharmony_ci					"offset %ld, coffset %ld, max layer %d, depth %d, "
9158c2ecf20Sopenharmony_ci					"bo size %ld) level0 (%d %d %d)\n",
9168c2ecf20Sopenharmony_ci					__func__, __LINE__, i, surf.layer_size,
9178c2ecf20Sopenharmony_ci					(unsigned long)texdw[3] << 8, moffset, mslice,
9188c2ecf20Sopenharmony_ci					d, radeon_bo_size(mipmap),
9198c2ecf20Sopenharmony_ci					width, height, depth);
9208c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n",
9218c2ecf20Sopenharmony_ci				 __func__, __LINE__, surf.nbx, surf.nby,
9228c2ecf20Sopenharmony_ci				surf.mode, surf.bpe, surf.nsamples,
9238c2ecf20Sopenharmony_ci				surf.bankw, surf.bankh,
9248c2ecf20Sopenharmony_ci				surf.tsplit, surf.mtilea);
9258c2ecf20Sopenharmony_ci			return -EINVAL;
9268c2ecf20Sopenharmony_ci		}
9278c2ecf20Sopenharmony_ci	}
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci	return 0;
9308c2ecf20Sopenharmony_ci}
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_cistatic int evergreen_cs_track_check(struct radeon_cs_parser *p)
9338c2ecf20Sopenharmony_ci{
9348c2ecf20Sopenharmony_ci	struct evergreen_cs_track *track = p->track;
9358c2ecf20Sopenharmony_ci	unsigned tmp, i;
9368c2ecf20Sopenharmony_ci	int r;
9378c2ecf20Sopenharmony_ci	unsigned buffer_mask = 0;
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci	/* check streamout */
9408c2ecf20Sopenharmony_ci	if (track->streamout_dirty && track->vgt_strmout_config) {
9418c2ecf20Sopenharmony_ci		for (i = 0; i < 4; i++) {
9428c2ecf20Sopenharmony_ci			if (track->vgt_strmout_config & (1 << i)) {
9438c2ecf20Sopenharmony_ci				buffer_mask |= (track->vgt_strmout_buffer_config >> (i * 4)) & 0xf;
9448c2ecf20Sopenharmony_ci			}
9458c2ecf20Sopenharmony_ci		}
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci		for (i = 0; i < 4; i++) {
9488c2ecf20Sopenharmony_ci			if (buffer_mask & (1 << i)) {
9498c2ecf20Sopenharmony_ci				if (track->vgt_strmout_bo[i]) {
9508c2ecf20Sopenharmony_ci					u64 offset = (u64)track->vgt_strmout_bo_offset[i] +
9518c2ecf20Sopenharmony_ci							(u64)track->vgt_strmout_size[i];
9528c2ecf20Sopenharmony_ci					if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) {
9538c2ecf20Sopenharmony_ci						DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n",
9548c2ecf20Sopenharmony_ci							  i, offset,
9558c2ecf20Sopenharmony_ci							  radeon_bo_size(track->vgt_strmout_bo[i]));
9568c2ecf20Sopenharmony_ci						return -EINVAL;
9578c2ecf20Sopenharmony_ci					}
9588c2ecf20Sopenharmony_ci				} else {
9598c2ecf20Sopenharmony_ci					dev_warn(p->dev, "No buffer for streamout %d\n", i);
9608c2ecf20Sopenharmony_ci					return -EINVAL;
9618c2ecf20Sopenharmony_ci				}
9628c2ecf20Sopenharmony_ci			}
9638c2ecf20Sopenharmony_ci		}
9648c2ecf20Sopenharmony_ci		track->streamout_dirty = false;
9658c2ecf20Sopenharmony_ci	}
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci	if (track->sx_misc_kill_all_prims)
9688c2ecf20Sopenharmony_ci		return 0;
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci	/* check that we have a cb for each enabled target
9718c2ecf20Sopenharmony_ci	 */
9728c2ecf20Sopenharmony_ci	if (track->cb_dirty) {
9738c2ecf20Sopenharmony_ci		tmp = track->cb_target_mask;
9748c2ecf20Sopenharmony_ci		for (i = 0; i < 8; i++) {
9758c2ecf20Sopenharmony_ci			u32 format = G_028C70_FORMAT(track->cb_color_info[i]);
9768c2ecf20Sopenharmony_ci
9778c2ecf20Sopenharmony_ci			if (format != V_028C70_COLOR_INVALID &&
9788c2ecf20Sopenharmony_ci			    (tmp >> (i * 4)) & 0xF) {
9798c2ecf20Sopenharmony_ci				/* at least one component is enabled */
9808c2ecf20Sopenharmony_ci				if (track->cb_color_bo[i] == NULL) {
9818c2ecf20Sopenharmony_ci					dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n",
9828c2ecf20Sopenharmony_ci						__func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i);
9838c2ecf20Sopenharmony_ci					return -EINVAL;
9848c2ecf20Sopenharmony_ci				}
9858c2ecf20Sopenharmony_ci				/* check cb */
9868c2ecf20Sopenharmony_ci				r = evergreen_cs_track_validate_cb(p, i);
9878c2ecf20Sopenharmony_ci				if (r) {
9888c2ecf20Sopenharmony_ci					return r;
9898c2ecf20Sopenharmony_ci				}
9908c2ecf20Sopenharmony_ci			}
9918c2ecf20Sopenharmony_ci		}
9928c2ecf20Sopenharmony_ci		track->cb_dirty = false;
9938c2ecf20Sopenharmony_ci	}
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci	if (track->db_dirty) {
9968c2ecf20Sopenharmony_ci		/* Check stencil buffer */
9978c2ecf20Sopenharmony_ci		if (G_028044_FORMAT(track->db_s_info) != V_028044_STENCIL_INVALID &&
9988c2ecf20Sopenharmony_ci		    G_028800_STENCIL_ENABLE(track->db_depth_control)) {
9998c2ecf20Sopenharmony_ci			r = evergreen_cs_track_validate_stencil(p);
10008c2ecf20Sopenharmony_ci			if (r)
10018c2ecf20Sopenharmony_ci				return r;
10028c2ecf20Sopenharmony_ci		}
10038c2ecf20Sopenharmony_ci		/* Check depth buffer */
10048c2ecf20Sopenharmony_ci		if (G_028040_FORMAT(track->db_z_info) != V_028040_Z_INVALID &&
10058c2ecf20Sopenharmony_ci		    G_028800_Z_ENABLE(track->db_depth_control)) {
10068c2ecf20Sopenharmony_ci			r = evergreen_cs_track_validate_depth(p);
10078c2ecf20Sopenharmony_ci			if (r)
10088c2ecf20Sopenharmony_ci				return r;
10098c2ecf20Sopenharmony_ci		}
10108c2ecf20Sopenharmony_ci		track->db_dirty = false;
10118c2ecf20Sopenharmony_ci	}
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	return 0;
10148c2ecf20Sopenharmony_ci}
10158c2ecf20Sopenharmony_ci
10168c2ecf20Sopenharmony_ci/**
10178c2ecf20Sopenharmony_ci * evergreen_cs_packet_parse_vline() - parse userspace VLINE packet
10188c2ecf20Sopenharmony_ci * @parser:		parser structure holding parsing context.
10198c2ecf20Sopenharmony_ci *
10208c2ecf20Sopenharmony_ci * This is an Evergreen(+)-specific function for parsing VLINE packets.
10218c2ecf20Sopenharmony_ci * Real work is done by r600_cs_common_vline_parse function.
10228c2ecf20Sopenharmony_ci * Here we just set up ASIC-specific register table and call
10238c2ecf20Sopenharmony_ci * the common implementation function.
10248c2ecf20Sopenharmony_ci */
10258c2ecf20Sopenharmony_cistatic int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
10268c2ecf20Sopenharmony_ci{
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci	static uint32_t vline_start_end[6] = {
10298c2ecf20Sopenharmony_ci		EVERGREEN_VLINE_START_END + EVERGREEN_CRTC0_REGISTER_OFFSET,
10308c2ecf20Sopenharmony_ci		EVERGREEN_VLINE_START_END + EVERGREEN_CRTC1_REGISTER_OFFSET,
10318c2ecf20Sopenharmony_ci		EVERGREEN_VLINE_START_END + EVERGREEN_CRTC2_REGISTER_OFFSET,
10328c2ecf20Sopenharmony_ci		EVERGREEN_VLINE_START_END + EVERGREEN_CRTC3_REGISTER_OFFSET,
10338c2ecf20Sopenharmony_ci		EVERGREEN_VLINE_START_END + EVERGREEN_CRTC4_REGISTER_OFFSET,
10348c2ecf20Sopenharmony_ci		EVERGREEN_VLINE_START_END + EVERGREEN_CRTC5_REGISTER_OFFSET
10358c2ecf20Sopenharmony_ci	};
10368c2ecf20Sopenharmony_ci	static uint32_t vline_status[6] = {
10378c2ecf20Sopenharmony_ci		EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET,
10388c2ecf20Sopenharmony_ci		EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET,
10398c2ecf20Sopenharmony_ci		EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET,
10408c2ecf20Sopenharmony_ci		EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET,
10418c2ecf20Sopenharmony_ci		EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET,
10428c2ecf20Sopenharmony_ci		EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET
10438c2ecf20Sopenharmony_ci	};
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci	return r600_cs_common_vline_parse(p, vline_start_end, vline_status);
10468c2ecf20Sopenharmony_ci}
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_cistatic int evergreen_packet0_check(struct radeon_cs_parser *p,
10498c2ecf20Sopenharmony_ci				   struct radeon_cs_packet *pkt,
10508c2ecf20Sopenharmony_ci				   unsigned idx, unsigned reg)
10518c2ecf20Sopenharmony_ci{
10528c2ecf20Sopenharmony_ci	int r;
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ci	switch (reg) {
10558c2ecf20Sopenharmony_ci	case EVERGREEN_VLINE_START_END:
10568c2ecf20Sopenharmony_ci		r = evergreen_cs_packet_parse_vline(p);
10578c2ecf20Sopenharmony_ci		if (r) {
10588c2ecf20Sopenharmony_ci			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
10598c2ecf20Sopenharmony_ci					idx, reg);
10608c2ecf20Sopenharmony_ci			return r;
10618c2ecf20Sopenharmony_ci		}
10628c2ecf20Sopenharmony_ci		break;
10638c2ecf20Sopenharmony_ci	default:
10648c2ecf20Sopenharmony_ci		pr_err("Forbidden register 0x%04X in cs at %d\n", reg, idx);
10658c2ecf20Sopenharmony_ci		return -EINVAL;
10668c2ecf20Sopenharmony_ci	}
10678c2ecf20Sopenharmony_ci	return 0;
10688c2ecf20Sopenharmony_ci}
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_cistatic int evergreen_cs_parse_packet0(struct radeon_cs_parser *p,
10718c2ecf20Sopenharmony_ci				      struct radeon_cs_packet *pkt)
10728c2ecf20Sopenharmony_ci{
10738c2ecf20Sopenharmony_ci	unsigned reg, i;
10748c2ecf20Sopenharmony_ci	unsigned idx;
10758c2ecf20Sopenharmony_ci	int r;
10768c2ecf20Sopenharmony_ci
10778c2ecf20Sopenharmony_ci	idx = pkt->idx + 1;
10788c2ecf20Sopenharmony_ci	reg = pkt->reg;
10798c2ecf20Sopenharmony_ci	for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
10808c2ecf20Sopenharmony_ci		r = evergreen_packet0_check(p, pkt, idx, reg);
10818c2ecf20Sopenharmony_ci		if (r) {
10828c2ecf20Sopenharmony_ci			return r;
10838c2ecf20Sopenharmony_ci		}
10848c2ecf20Sopenharmony_ci	}
10858c2ecf20Sopenharmony_ci	return 0;
10868c2ecf20Sopenharmony_ci}
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci/**
10898c2ecf20Sopenharmony_ci * evergreen_cs_handle_reg() - process registers that need special handling.
10908c2ecf20Sopenharmony_ci * @parser: parser structure holding parsing context
10918c2ecf20Sopenharmony_ci * @reg: register we are testing
10928c2ecf20Sopenharmony_ci * @idx: index into the cs buffer
10938c2ecf20Sopenharmony_ci */
10948c2ecf20Sopenharmony_cistatic int evergreen_cs_handle_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
10958c2ecf20Sopenharmony_ci{
10968c2ecf20Sopenharmony_ci	struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track;
10978c2ecf20Sopenharmony_ci	struct radeon_bo_list *reloc;
10988c2ecf20Sopenharmony_ci	u32 tmp, *ib;
10998c2ecf20Sopenharmony_ci	int r;
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	ib = p->ib.ptr;
11028c2ecf20Sopenharmony_ci	switch (reg) {
11038c2ecf20Sopenharmony_ci	/* force following reg to 0 in an attempt to disable out buffer
11048c2ecf20Sopenharmony_ci	 * which will need us to better understand how it works to perform
11058c2ecf20Sopenharmony_ci	 * security check on it (Jerome)
11068c2ecf20Sopenharmony_ci	 */
11078c2ecf20Sopenharmony_ci	case SQ_ESGS_RING_SIZE:
11088c2ecf20Sopenharmony_ci	case SQ_GSVS_RING_SIZE:
11098c2ecf20Sopenharmony_ci	case SQ_ESTMP_RING_SIZE:
11108c2ecf20Sopenharmony_ci	case SQ_GSTMP_RING_SIZE:
11118c2ecf20Sopenharmony_ci	case SQ_HSTMP_RING_SIZE:
11128c2ecf20Sopenharmony_ci	case SQ_LSTMP_RING_SIZE:
11138c2ecf20Sopenharmony_ci	case SQ_PSTMP_RING_SIZE:
11148c2ecf20Sopenharmony_ci	case SQ_VSTMP_RING_SIZE:
11158c2ecf20Sopenharmony_ci	case SQ_ESGS_RING_ITEMSIZE:
11168c2ecf20Sopenharmony_ci	case SQ_ESTMP_RING_ITEMSIZE:
11178c2ecf20Sopenharmony_ci	case SQ_GSTMP_RING_ITEMSIZE:
11188c2ecf20Sopenharmony_ci	case SQ_GSVS_RING_ITEMSIZE:
11198c2ecf20Sopenharmony_ci	case SQ_GS_VERT_ITEMSIZE:
11208c2ecf20Sopenharmony_ci	case SQ_GS_VERT_ITEMSIZE_1:
11218c2ecf20Sopenharmony_ci	case SQ_GS_VERT_ITEMSIZE_2:
11228c2ecf20Sopenharmony_ci	case SQ_GS_VERT_ITEMSIZE_3:
11238c2ecf20Sopenharmony_ci	case SQ_GSVS_RING_OFFSET_1:
11248c2ecf20Sopenharmony_ci	case SQ_GSVS_RING_OFFSET_2:
11258c2ecf20Sopenharmony_ci	case SQ_GSVS_RING_OFFSET_3:
11268c2ecf20Sopenharmony_ci	case SQ_HSTMP_RING_ITEMSIZE:
11278c2ecf20Sopenharmony_ci	case SQ_LSTMP_RING_ITEMSIZE:
11288c2ecf20Sopenharmony_ci	case SQ_PSTMP_RING_ITEMSIZE:
11298c2ecf20Sopenharmony_ci	case SQ_VSTMP_RING_ITEMSIZE:
11308c2ecf20Sopenharmony_ci	case VGT_TF_RING_SIZE:
11318c2ecf20Sopenharmony_ci		/* get value to populate the IB don't remove */
11328c2ecf20Sopenharmony_ci		/*tmp =radeon_get_ib_value(p, idx);
11338c2ecf20Sopenharmony_ci		  ib[idx] = 0;*/
11348c2ecf20Sopenharmony_ci		break;
11358c2ecf20Sopenharmony_ci	case SQ_ESGS_RING_BASE:
11368c2ecf20Sopenharmony_ci	case SQ_GSVS_RING_BASE:
11378c2ecf20Sopenharmony_ci	case SQ_ESTMP_RING_BASE:
11388c2ecf20Sopenharmony_ci	case SQ_GSTMP_RING_BASE:
11398c2ecf20Sopenharmony_ci	case SQ_HSTMP_RING_BASE:
11408c2ecf20Sopenharmony_ci	case SQ_LSTMP_RING_BASE:
11418c2ecf20Sopenharmony_ci	case SQ_PSTMP_RING_BASE:
11428c2ecf20Sopenharmony_ci	case SQ_VSTMP_RING_BASE:
11438c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
11448c2ecf20Sopenharmony_ci		if (r) {
11458c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
11468c2ecf20Sopenharmony_ci					"0x%04X\n", reg);
11478c2ecf20Sopenharmony_ci			return -EINVAL;
11488c2ecf20Sopenharmony_ci		}
11498c2ecf20Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
11508c2ecf20Sopenharmony_ci		break;
11518c2ecf20Sopenharmony_ci	case DB_DEPTH_CONTROL:
11528c2ecf20Sopenharmony_ci		track->db_depth_control = radeon_get_ib_value(p, idx);
11538c2ecf20Sopenharmony_ci		track->db_dirty = true;
11548c2ecf20Sopenharmony_ci		break;
11558c2ecf20Sopenharmony_ci	case CAYMAN_DB_EQAA:
11568c2ecf20Sopenharmony_ci		if (p->rdev->family < CHIP_CAYMAN) {
11578c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
11588c2ecf20Sopenharmony_ci				 "0x%04X\n", reg);
11598c2ecf20Sopenharmony_ci			return -EINVAL;
11608c2ecf20Sopenharmony_ci		}
11618c2ecf20Sopenharmony_ci		break;
11628c2ecf20Sopenharmony_ci	case CAYMAN_DB_DEPTH_INFO:
11638c2ecf20Sopenharmony_ci		if (p->rdev->family < CHIP_CAYMAN) {
11648c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
11658c2ecf20Sopenharmony_ci				 "0x%04X\n", reg);
11668c2ecf20Sopenharmony_ci			return -EINVAL;
11678c2ecf20Sopenharmony_ci		}
11688c2ecf20Sopenharmony_ci		break;
11698c2ecf20Sopenharmony_ci	case DB_Z_INFO:
11708c2ecf20Sopenharmony_ci		track->db_z_info = radeon_get_ib_value(p, idx);
11718c2ecf20Sopenharmony_ci		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
11728c2ecf20Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, 0);
11738c2ecf20Sopenharmony_ci			if (r) {
11748c2ecf20Sopenharmony_ci				dev_warn(p->dev, "bad SET_CONTEXT_REG "
11758c2ecf20Sopenharmony_ci						"0x%04X\n", reg);
11768c2ecf20Sopenharmony_ci				return -EINVAL;
11778c2ecf20Sopenharmony_ci			}
11788c2ecf20Sopenharmony_ci			ib[idx] &= ~Z_ARRAY_MODE(0xf);
11798c2ecf20Sopenharmony_ci			track->db_z_info &= ~Z_ARRAY_MODE(0xf);
11808c2ecf20Sopenharmony_ci			ib[idx] |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags));
11818c2ecf20Sopenharmony_ci			track->db_z_info |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags));
11828c2ecf20Sopenharmony_ci			if (reloc->tiling_flags & RADEON_TILING_MACRO) {
11838c2ecf20Sopenharmony_ci				unsigned bankw, bankh, mtaspect, tile_split;
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_ci				evergreen_tiling_fields(reloc->tiling_flags,
11868c2ecf20Sopenharmony_ci							&bankw, &bankh, &mtaspect,
11878c2ecf20Sopenharmony_ci							&tile_split);
11888c2ecf20Sopenharmony_ci				ib[idx] |= DB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
11898c2ecf20Sopenharmony_ci				ib[idx] |= DB_TILE_SPLIT(tile_split) |
11908c2ecf20Sopenharmony_ci						DB_BANK_WIDTH(bankw) |
11918c2ecf20Sopenharmony_ci						DB_BANK_HEIGHT(bankh) |
11928c2ecf20Sopenharmony_ci						DB_MACRO_TILE_ASPECT(mtaspect);
11938c2ecf20Sopenharmony_ci			}
11948c2ecf20Sopenharmony_ci		}
11958c2ecf20Sopenharmony_ci		track->db_dirty = true;
11968c2ecf20Sopenharmony_ci		break;
11978c2ecf20Sopenharmony_ci	case DB_STENCIL_INFO:
11988c2ecf20Sopenharmony_ci		track->db_s_info = radeon_get_ib_value(p, idx);
11998c2ecf20Sopenharmony_ci		track->db_dirty = true;
12008c2ecf20Sopenharmony_ci		break;
12018c2ecf20Sopenharmony_ci	case DB_DEPTH_VIEW:
12028c2ecf20Sopenharmony_ci		track->db_depth_view = radeon_get_ib_value(p, idx);
12038c2ecf20Sopenharmony_ci		track->db_dirty = true;
12048c2ecf20Sopenharmony_ci		break;
12058c2ecf20Sopenharmony_ci	case DB_DEPTH_SIZE:
12068c2ecf20Sopenharmony_ci		track->db_depth_size = radeon_get_ib_value(p, idx);
12078c2ecf20Sopenharmony_ci		track->db_dirty = true;
12088c2ecf20Sopenharmony_ci		break;
12098c2ecf20Sopenharmony_ci	case R_02805C_DB_DEPTH_SLICE:
12108c2ecf20Sopenharmony_ci		track->db_depth_slice = radeon_get_ib_value(p, idx);
12118c2ecf20Sopenharmony_ci		track->db_dirty = true;
12128c2ecf20Sopenharmony_ci		break;
12138c2ecf20Sopenharmony_ci	case DB_Z_READ_BASE:
12148c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
12158c2ecf20Sopenharmony_ci		if (r) {
12168c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
12178c2ecf20Sopenharmony_ci					"0x%04X\n", reg);
12188c2ecf20Sopenharmony_ci			return -EINVAL;
12198c2ecf20Sopenharmony_ci		}
12208c2ecf20Sopenharmony_ci		track->db_z_read_offset = radeon_get_ib_value(p, idx);
12218c2ecf20Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
12228c2ecf20Sopenharmony_ci		track->db_z_read_bo = reloc->robj;
12238c2ecf20Sopenharmony_ci		track->db_dirty = true;
12248c2ecf20Sopenharmony_ci		break;
12258c2ecf20Sopenharmony_ci	case DB_Z_WRITE_BASE:
12268c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
12278c2ecf20Sopenharmony_ci		if (r) {
12288c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
12298c2ecf20Sopenharmony_ci					"0x%04X\n", reg);
12308c2ecf20Sopenharmony_ci			return -EINVAL;
12318c2ecf20Sopenharmony_ci		}
12328c2ecf20Sopenharmony_ci		track->db_z_write_offset = radeon_get_ib_value(p, idx);
12338c2ecf20Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
12348c2ecf20Sopenharmony_ci		track->db_z_write_bo = reloc->robj;
12358c2ecf20Sopenharmony_ci		track->db_dirty = true;
12368c2ecf20Sopenharmony_ci		break;
12378c2ecf20Sopenharmony_ci	case DB_STENCIL_READ_BASE:
12388c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
12398c2ecf20Sopenharmony_ci		if (r) {
12408c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
12418c2ecf20Sopenharmony_ci					"0x%04X\n", reg);
12428c2ecf20Sopenharmony_ci			return -EINVAL;
12438c2ecf20Sopenharmony_ci		}
12448c2ecf20Sopenharmony_ci		track->db_s_read_offset = radeon_get_ib_value(p, idx);
12458c2ecf20Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
12468c2ecf20Sopenharmony_ci		track->db_s_read_bo = reloc->robj;
12478c2ecf20Sopenharmony_ci		track->db_dirty = true;
12488c2ecf20Sopenharmony_ci		break;
12498c2ecf20Sopenharmony_ci	case DB_STENCIL_WRITE_BASE:
12508c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
12518c2ecf20Sopenharmony_ci		if (r) {
12528c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
12538c2ecf20Sopenharmony_ci					"0x%04X\n", reg);
12548c2ecf20Sopenharmony_ci			return -EINVAL;
12558c2ecf20Sopenharmony_ci		}
12568c2ecf20Sopenharmony_ci		track->db_s_write_offset = radeon_get_ib_value(p, idx);
12578c2ecf20Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
12588c2ecf20Sopenharmony_ci		track->db_s_write_bo = reloc->robj;
12598c2ecf20Sopenharmony_ci		track->db_dirty = true;
12608c2ecf20Sopenharmony_ci		break;
12618c2ecf20Sopenharmony_ci	case VGT_STRMOUT_CONFIG:
12628c2ecf20Sopenharmony_ci		track->vgt_strmout_config = radeon_get_ib_value(p, idx);
12638c2ecf20Sopenharmony_ci		track->streamout_dirty = true;
12648c2ecf20Sopenharmony_ci		break;
12658c2ecf20Sopenharmony_ci	case VGT_STRMOUT_BUFFER_CONFIG:
12668c2ecf20Sopenharmony_ci		track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx);
12678c2ecf20Sopenharmony_ci		track->streamout_dirty = true;
12688c2ecf20Sopenharmony_ci		break;
12698c2ecf20Sopenharmony_ci	case VGT_STRMOUT_BUFFER_BASE_0:
12708c2ecf20Sopenharmony_ci	case VGT_STRMOUT_BUFFER_BASE_1:
12718c2ecf20Sopenharmony_ci	case VGT_STRMOUT_BUFFER_BASE_2:
12728c2ecf20Sopenharmony_ci	case VGT_STRMOUT_BUFFER_BASE_3:
12738c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
12748c2ecf20Sopenharmony_ci		if (r) {
12758c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
12768c2ecf20Sopenharmony_ci					"0x%04X\n", reg);
12778c2ecf20Sopenharmony_ci			return -EINVAL;
12788c2ecf20Sopenharmony_ci		}
12798c2ecf20Sopenharmony_ci		tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
12808c2ecf20Sopenharmony_ci		track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
12818c2ecf20Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
12828c2ecf20Sopenharmony_ci		track->vgt_strmout_bo[tmp] = reloc->robj;
12838c2ecf20Sopenharmony_ci		track->streamout_dirty = true;
12848c2ecf20Sopenharmony_ci		break;
12858c2ecf20Sopenharmony_ci	case VGT_STRMOUT_BUFFER_SIZE_0:
12868c2ecf20Sopenharmony_ci	case VGT_STRMOUT_BUFFER_SIZE_1:
12878c2ecf20Sopenharmony_ci	case VGT_STRMOUT_BUFFER_SIZE_2:
12888c2ecf20Sopenharmony_ci	case VGT_STRMOUT_BUFFER_SIZE_3:
12898c2ecf20Sopenharmony_ci		tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
12908c2ecf20Sopenharmony_ci		/* size in register is DWs, convert to bytes */
12918c2ecf20Sopenharmony_ci		track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4;
12928c2ecf20Sopenharmony_ci		track->streamout_dirty = true;
12938c2ecf20Sopenharmony_ci		break;
12948c2ecf20Sopenharmony_ci	case CP_COHER_BASE:
12958c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
12968c2ecf20Sopenharmony_ci		if (r) {
12978c2ecf20Sopenharmony_ci			dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
12988c2ecf20Sopenharmony_ci					"0x%04X\n", reg);
12998c2ecf20Sopenharmony_ci			return -EINVAL;
13008c2ecf20Sopenharmony_ci		}
13018c2ecf20Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
13028c2ecf20Sopenharmony_ci		break;
13038c2ecf20Sopenharmony_ci	case CB_TARGET_MASK:
13048c2ecf20Sopenharmony_ci		track->cb_target_mask = radeon_get_ib_value(p, idx);
13058c2ecf20Sopenharmony_ci		track->cb_dirty = true;
13068c2ecf20Sopenharmony_ci		break;
13078c2ecf20Sopenharmony_ci	case CB_SHADER_MASK:
13088c2ecf20Sopenharmony_ci		track->cb_shader_mask = radeon_get_ib_value(p, idx);
13098c2ecf20Sopenharmony_ci		track->cb_dirty = true;
13108c2ecf20Sopenharmony_ci		break;
13118c2ecf20Sopenharmony_ci	case PA_SC_AA_CONFIG:
13128c2ecf20Sopenharmony_ci		if (p->rdev->family >= CHIP_CAYMAN) {
13138c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
13148c2ecf20Sopenharmony_ci				 "0x%04X\n", reg);
13158c2ecf20Sopenharmony_ci			return -EINVAL;
13168c2ecf20Sopenharmony_ci		}
13178c2ecf20Sopenharmony_ci		tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK;
13188c2ecf20Sopenharmony_ci		track->nsamples = 1 << tmp;
13198c2ecf20Sopenharmony_ci		break;
13208c2ecf20Sopenharmony_ci	case CAYMAN_PA_SC_AA_CONFIG:
13218c2ecf20Sopenharmony_ci		if (p->rdev->family < CHIP_CAYMAN) {
13228c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
13238c2ecf20Sopenharmony_ci				 "0x%04X\n", reg);
13248c2ecf20Sopenharmony_ci			return -EINVAL;
13258c2ecf20Sopenharmony_ci		}
13268c2ecf20Sopenharmony_ci		tmp = radeon_get_ib_value(p, idx) & CAYMAN_MSAA_NUM_SAMPLES_MASK;
13278c2ecf20Sopenharmony_ci		track->nsamples = 1 << tmp;
13288c2ecf20Sopenharmony_ci		break;
13298c2ecf20Sopenharmony_ci	case CB_COLOR0_VIEW:
13308c2ecf20Sopenharmony_ci	case CB_COLOR1_VIEW:
13318c2ecf20Sopenharmony_ci	case CB_COLOR2_VIEW:
13328c2ecf20Sopenharmony_ci	case CB_COLOR3_VIEW:
13338c2ecf20Sopenharmony_ci	case CB_COLOR4_VIEW:
13348c2ecf20Sopenharmony_ci	case CB_COLOR5_VIEW:
13358c2ecf20Sopenharmony_ci	case CB_COLOR6_VIEW:
13368c2ecf20Sopenharmony_ci	case CB_COLOR7_VIEW:
13378c2ecf20Sopenharmony_ci		tmp = (reg - CB_COLOR0_VIEW) / 0x3c;
13388c2ecf20Sopenharmony_ci		track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
13398c2ecf20Sopenharmony_ci		track->cb_dirty = true;
13408c2ecf20Sopenharmony_ci		break;
13418c2ecf20Sopenharmony_ci	case CB_COLOR8_VIEW:
13428c2ecf20Sopenharmony_ci	case CB_COLOR9_VIEW:
13438c2ecf20Sopenharmony_ci	case CB_COLOR10_VIEW:
13448c2ecf20Sopenharmony_ci	case CB_COLOR11_VIEW:
13458c2ecf20Sopenharmony_ci		tmp = ((reg - CB_COLOR8_VIEW) / 0x1c) + 8;
13468c2ecf20Sopenharmony_ci		track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
13478c2ecf20Sopenharmony_ci		track->cb_dirty = true;
13488c2ecf20Sopenharmony_ci		break;
13498c2ecf20Sopenharmony_ci	case CB_COLOR0_INFO:
13508c2ecf20Sopenharmony_ci	case CB_COLOR1_INFO:
13518c2ecf20Sopenharmony_ci	case CB_COLOR2_INFO:
13528c2ecf20Sopenharmony_ci	case CB_COLOR3_INFO:
13538c2ecf20Sopenharmony_ci	case CB_COLOR4_INFO:
13548c2ecf20Sopenharmony_ci	case CB_COLOR5_INFO:
13558c2ecf20Sopenharmony_ci	case CB_COLOR6_INFO:
13568c2ecf20Sopenharmony_ci	case CB_COLOR7_INFO:
13578c2ecf20Sopenharmony_ci		tmp = (reg - CB_COLOR0_INFO) / 0x3c;
13588c2ecf20Sopenharmony_ci		track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
13598c2ecf20Sopenharmony_ci		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
13608c2ecf20Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, 0);
13618c2ecf20Sopenharmony_ci			if (r) {
13628c2ecf20Sopenharmony_ci				dev_warn(p->dev, "bad SET_CONTEXT_REG "
13638c2ecf20Sopenharmony_ci						"0x%04X\n", reg);
13648c2ecf20Sopenharmony_ci				return -EINVAL;
13658c2ecf20Sopenharmony_ci			}
13668c2ecf20Sopenharmony_ci			ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags));
13678c2ecf20Sopenharmony_ci			track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags));
13688c2ecf20Sopenharmony_ci		}
13698c2ecf20Sopenharmony_ci		track->cb_dirty = true;
13708c2ecf20Sopenharmony_ci		break;
13718c2ecf20Sopenharmony_ci	case CB_COLOR8_INFO:
13728c2ecf20Sopenharmony_ci	case CB_COLOR9_INFO:
13738c2ecf20Sopenharmony_ci	case CB_COLOR10_INFO:
13748c2ecf20Sopenharmony_ci	case CB_COLOR11_INFO:
13758c2ecf20Sopenharmony_ci		tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;
13768c2ecf20Sopenharmony_ci		track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
13778c2ecf20Sopenharmony_ci		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
13788c2ecf20Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, 0);
13798c2ecf20Sopenharmony_ci			if (r) {
13808c2ecf20Sopenharmony_ci				dev_warn(p->dev, "bad SET_CONTEXT_REG "
13818c2ecf20Sopenharmony_ci						"0x%04X\n", reg);
13828c2ecf20Sopenharmony_ci				return -EINVAL;
13838c2ecf20Sopenharmony_ci			}
13848c2ecf20Sopenharmony_ci			ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags));
13858c2ecf20Sopenharmony_ci			track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags));
13868c2ecf20Sopenharmony_ci		}
13878c2ecf20Sopenharmony_ci		track->cb_dirty = true;
13888c2ecf20Sopenharmony_ci		break;
13898c2ecf20Sopenharmony_ci	case CB_COLOR0_PITCH:
13908c2ecf20Sopenharmony_ci	case CB_COLOR1_PITCH:
13918c2ecf20Sopenharmony_ci	case CB_COLOR2_PITCH:
13928c2ecf20Sopenharmony_ci	case CB_COLOR3_PITCH:
13938c2ecf20Sopenharmony_ci	case CB_COLOR4_PITCH:
13948c2ecf20Sopenharmony_ci	case CB_COLOR5_PITCH:
13958c2ecf20Sopenharmony_ci	case CB_COLOR6_PITCH:
13968c2ecf20Sopenharmony_ci	case CB_COLOR7_PITCH:
13978c2ecf20Sopenharmony_ci		tmp = (reg - CB_COLOR0_PITCH) / 0x3c;
13988c2ecf20Sopenharmony_ci		track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
13998c2ecf20Sopenharmony_ci		track->cb_dirty = true;
14008c2ecf20Sopenharmony_ci		break;
14018c2ecf20Sopenharmony_ci	case CB_COLOR8_PITCH:
14028c2ecf20Sopenharmony_ci	case CB_COLOR9_PITCH:
14038c2ecf20Sopenharmony_ci	case CB_COLOR10_PITCH:
14048c2ecf20Sopenharmony_ci	case CB_COLOR11_PITCH:
14058c2ecf20Sopenharmony_ci		tmp = ((reg - CB_COLOR8_PITCH) / 0x1c) + 8;
14068c2ecf20Sopenharmony_ci		track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
14078c2ecf20Sopenharmony_ci		track->cb_dirty = true;
14088c2ecf20Sopenharmony_ci		break;
14098c2ecf20Sopenharmony_ci	case CB_COLOR0_SLICE:
14108c2ecf20Sopenharmony_ci	case CB_COLOR1_SLICE:
14118c2ecf20Sopenharmony_ci	case CB_COLOR2_SLICE:
14128c2ecf20Sopenharmony_ci	case CB_COLOR3_SLICE:
14138c2ecf20Sopenharmony_ci	case CB_COLOR4_SLICE:
14148c2ecf20Sopenharmony_ci	case CB_COLOR5_SLICE:
14158c2ecf20Sopenharmony_ci	case CB_COLOR6_SLICE:
14168c2ecf20Sopenharmony_ci	case CB_COLOR7_SLICE:
14178c2ecf20Sopenharmony_ci		tmp = (reg - CB_COLOR0_SLICE) / 0x3c;
14188c2ecf20Sopenharmony_ci		track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
14198c2ecf20Sopenharmony_ci		track->cb_color_slice_idx[tmp] = idx;
14208c2ecf20Sopenharmony_ci		track->cb_dirty = true;
14218c2ecf20Sopenharmony_ci		break;
14228c2ecf20Sopenharmony_ci	case CB_COLOR8_SLICE:
14238c2ecf20Sopenharmony_ci	case CB_COLOR9_SLICE:
14248c2ecf20Sopenharmony_ci	case CB_COLOR10_SLICE:
14258c2ecf20Sopenharmony_ci	case CB_COLOR11_SLICE:
14268c2ecf20Sopenharmony_ci		tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8;
14278c2ecf20Sopenharmony_ci		track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
14288c2ecf20Sopenharmony_ci		track->cb_color_slice_idx[tmp] = idx;
14298c2ecf20Sopenharmony_ci		track->cb_dirty = true;
14308c2ecf20Sopenharmony_ci		break;
14318c2ecf20Sopenharmony_ci	case CB_COLOR0_ATTRIB:
14328c2ecf20Sopenharmony_ci	case CB_COLOR1_ATTRIB:
14338c2ecf20Sopenharmony_ci	case CB_COLOR2_ATTRIB:
14348c2ecf20Sopenharmony_ci	case CB_COLOR3_ATTRIB:
14358c2ecf20Sopenharmony_ci	case CB_COLOR4_ATTRIB:
14368c2ecf20Sopenharmony_ci	case CB_COLOR5_ATTRIB:
14378c2ecf20Sopenharmony_ci	case CB_COLOR6_ATTRIB:
14388c2ecf20Sopenharmony_ci	case CB_COLOR7_ATTRIB:
14398c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
14408c2ecf20Sopenharmony_ci		if (r) {
14418c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
14428c2ecf20Sopenharmony_ci					"0x%04X\n", reg);
14438c2ecf20Sopenharmony_ci			return -EINVAL;
14448c2ecf20Sopenharmony_ci		}
14458c2ecf20Sopenharmony_ci		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
14468c2ecf20Sopenharmony_ci			if (reloc->tiling_flags & RADEON_TILING_MACRO) {
14478c2ecf20Sopenharmony_ci				unsigned bankw, bankh, mtaspect, tile_split;
14488c2ecf20Sopenharmony_ci
14498c2ecf20Sopenharmony_ci				evergreen_tiling_fields(reloc->tiling_flags,
14508c2ecf20Sopenharmony_ci							&bankw, &bankh, &mtaspect,
14518c2ecf20Sopenharmony_ci							&tile_split);
14528c2ecf20Sopenharmony_ci				ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
14538c2ecf20Sopenharmony_ci				ib[idx] |= CB_TILE_SPLIT(tile_split) |
14548c2ecf20Sopenharmony_ci					   CB_BANK_WIDTH(bankw) |
14558c2ecf20Sopenharmony_ci					   CB_BANK_HEIGHT(bankh) |
14568c2ecf20Sopenharmony_ci					   CB_MACRO_TILE_ASPECT(mtaspect);
14578c2ecf20Sopenharmony_ci			}
14588c2ecf20Sopenharmony_ci		}
14598c2ecf20Sopenharmony_ci		tmp = ((reg - CB_COLOR0_ATTRIB) / 0x3c);
14608c2ecf20Sopenharmony_ci		track->cb_color_attrib[tmp] = ib[idx];
14618c2ecf20Sopenharmony_ci		track->cb_dirty = true;
14628c2ecf20Sopenharmony_ci		break;
14638c2ecf20Sopenharmony_ci	case CB_COLOR8_ATTRIB:
14648c2ecf20Sopenharmony_ci	case CB_COLOR9_ATTRIB:
14658c2ecf20Sopenharmony_ci	case CB_COLOR10_ATTRIB:
14668c2ecf20Sopenharmony_ci	case CB_COLOR11_ATTRIB:
14678c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
14688c2ecf20Sopenharmony_ci		if (r) {
14698c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
14708c2ecf20Sopenharmony_ci					"0x%04X\n", reg);
14718c2ecf20Sopenharmony_ci			return -EINVAL;
14728c2ecf20Sopenharmony_ci		}
14738c2ecf20Sopenharmony_ci		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
14748c2ecf20Sopenharmony_ci			if (reloc->tiling_flags & RADEON_TILING_MACRO) {
14758c2ecf20Sopenharmony_ci				unsigned bankw, bankh, mtaspect, tile_split;
14768c2ecf20Sopenharmony_ci
14778c2ecf20Sopenharmony_ci				evergreen_tiling_fields(reloc->tiling_flags,
14788c2ecf20Sopenharmony_ci							&bankw, &bankh, &mtaspect,
14798c2ecf20Sopenharmony_ci							&tile_split);
14808c2ecf20Sopenharmony_ci				ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
14818c2ecf20Sopenharmony_ci				ib[idx] |= CB_TILE_SPLIT(tile_split) |
14828c2ecf20Sopenharmony_ci					   CB_BANK_WIDTH(bankw) |
14838c2ecf20Sopenharmony_ci					   CB_BANK_HEIGHT(bankh) |
14848c2ecf20Sopenharmony_ci					   CB_MACRO_TILE_ASPECT(mtaspect);
14858c2ecf20Sopenharmony_ci			}
14868c2ecf20Sopenharmony_ci		}
14878c2ecf20Sopenharmony_ci		tmp = ((reg - CB_COLOR8_ATTRIB) / 0x1c) + 8;
14888c2ecf20Sopenharmony_ci		track->cb_color_attrib[tmp] = ib[idx];
14898c2ecf20Sopenharmony_ci		track->cb_dirty = true;
14908c2ecf20Sopenharmony_ci		break;
14918c2ecf20Sopenharmony_ci	case CB_COLOR0_FMASK:
14928c2ecf20Sopenharmony_ci	case CB_COLOR1_FMASK:
14938c2ecf20Sopenharmony_ci	case CB_COLOR2_FMASK:
14948c2ecf20Sopenharmony_ci	case CB_COLOR3_FMASK:
14958c2ecf20Sopenharmony_ci	case CB_COLOR4_FMASK:
14968c2ecf20Sopenharmony_ci	case CB_COLOR5_FMASK:
14978c2ecf20Sopenharmony_ci	case CB_COLOR6_FMASK:
14988c2ecf20Sopenharmony_ci	case CB_COLOR7_FMASK:
14998c2ecf20Sopenharmony_ci		tmp = (reg - CB_COLOR0_FMASK) / 0x3c;
15008c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
15018c2ecf20Sopenharmony_ci		if (r) {
15028c2ecf20Sopenharmony_ci			dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
15038c2ecf20Sopenharmony_ci			return -EINVAL;
15048c2ecf20Sopenharmony_ci		}
15058c2ecf20Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
15068c2ecf20Sopenharmony_ci		track->cb_color_fmask_bo[tmp] = reloc->robj;
15078c2ecf20Sopenharmony_ci		break;
15088c2ecf20Sopenharmony_ci	case CB_COLOR0_CMASK:
15098c2ecf20Sopenharmony_ci	case CB_COLOR1_CMASK:
15108c2ecf20Sopenharmony_ci	case CB_COLOR2_CMASK:
15118c2ecf20Sopenharmony_ci	case CB_COLOR3_CMASK:
15128c2ecf20Sopenharmony_ci	case CB_COLOR4_CMASK:
15138c2ecf20Sopenharmony_ci	case CB_COLOR5_CMASK:
15148c2ecf20Sopenharmony_ci	case CB_COLOR6_CMASK:
15158c2ecf20Sopenharmony_ci	case CB_COLOR7_CMASK:
15168c2ecf20Sopenharmony_ci		tmp = (reg - CB_COLOR0_CMASK) / 0x3c;
15178c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
15188c2ecf20Sopenharmony_ci		if (r) {
15198c2ecf20Sopenharmony_ci			dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
15208c2ecf20Sopenharmony_ci			return -EINVAL;
15218c2ecf20Sopenharmony_ci		}
15228c2ecf20Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
15238c2ecf20Sopenharmony_ci		track->cb_color_cmask_bo[tmp] = reloc->robj;
15248c2ecf20Sopenharmony_ci		break;
15258c2ecf20Sopenharmony_ci	case CB_COLOR0_FMASK_SLICE:
15268c2ecf20Sopenharmony_ci	case CB_COLOR1_FMASK_SLICE:
15278c2ecf20Sopenharmony_ci	case CB_COLOR2_FMASK_SLICE:
15288c2ecf20Sopenharmony_ci	case CB_COLOR3_FMASK_SLICE:
15298c2ecf20Sopenharmony_ci	case CB_COLOR4_FMASK_SLICE:
15308c2ecf20Sopenharmony_ci	case CB_COLOR5_FMASK_SLICE:
15318c2ecf20Sopenharmony_ci	case CB_COLOR6_FMASK_SLICE:
15328c2ecf20Sopenharmony_ci	case CB_COLOR7_FMASK_SLICE:
15338c2ecf20Sopenharmony_ci		tmp = (reg - CB_COLOR0_FMASK_SLICE) / 0x3c;
15348c2ecf20Sopenharmony_ci		track->cb_color_fmask_slice[tmp] = radeon_get_ib_value(p, idx);
15358c2ecf20Sopenharmony_ci		break;
15368c2ecf20Sopenharmony_ci	case CB_COLOR0_CMASK_SLICE:
15378c2ecf20Sopenharmony_ci	case CB_COLOR1_CMASK_SLICE:
15388c2ecf20Sopenharmony_ci	case CB_COLOR2_CMASK_SLICE:
15398c2ecf20Sopenharmony_ci	case CB_COLOR3_CMASK_SLICE:
15408c2ecf20Sopenharmony_ci	case CB_COLOR4_CMASK_SLICE:
15418c2ecf20Sopenharmony_ci	case CB_COLOR5_CMASK_SLICE:
15428c2ecf20Sopenharmony_ci	case CB_COLOR6_CMASK_SLICE:
15438c2ecf20Sopenharmony_ci	case CB_COLOR7_CMASK_SLICE:
15448c2ecf20Sopenharmony_ci		tmp = (reg - CB_COLOR0_CMASK_SLICE) / 0x3c;
15458c2ecf20Sopenharmony_ci		track->cb_color_cmask_slice[tmp] = radeon_get_ib_value(p, idx);
15468c2ecf20Sopenharmony_ci		break;
15478c2ecf20Sopenharmony_ci	case CB_COLOR0_BASE:
15488c2ecf20Sopenharmony_ci	case CB_COLOR1_BASE:
15498c2ecf20Sopenharmony_ci	case CB_COLOR2_BASE:
15508c2ecf20Sopenharmony_ci	case CB_COLOR3_BASE:
15518c2ecf20Sopenharmony_ci	case CB_COLOR4_BASE:
15528c2ecf20Sopenharmony_ci	case CB_COLOR5_BASE:
15538c2ecf20Sopenharmony_ci	case CB_COLOR6_BASE:
15548c2ecf20Sopenharmony_ci	case CB_COLOR7_BASE:
15558c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
15568c2ecf20Sopenharmony_ci		if (r) {
15578c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
15588c2ecf20Sopenharmony_ci					"0x%04X\n", reg);
15598c2ecf20Sopenharmony_ci			return -EINVAL;
15608c2ecf20Sopenharmony_ci		}
15618c2ecf20Sopenharmony_ci		tmp = (reg - CB_COLOR0_BASE) / 0x3c;
15628c2ecf20Sopenharmony_ci		track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
15638c2ecf20Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
15648c2ecf20Sopenharmony_ci		track->cb_color_bo[tmp] = reloc->robj;
15658c2ecf20Sopenharmony_ci		track->cb_dirty = true;
15668c2ecf20Sopenharmony_ci		break;
15678c2ecf20Sopenharmony_ci	case CB_COLOR8_BASE:
15688c2ecf20Sopenharmony_ci	case CB_COLOR9_BASE:
15698c2ecf20Sopenharmony_ci	case CB_COLOR10_BASE:
15708c2ecf20Sopenharmony_ci	case CB_COLOR11_BASE:
15718c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
15728c2ecf20Sopenharmony_ci		if (r) {
15738c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
15748c2ecf20Sopenharmony_ci					"0x%04X\n", reg);
15758c2ecf20Sopenharmony_ci			return -EINVAL;
15768c2ecf20Sopenharmony_ci		}
15778c2ecf20Sopenharmony_ci		tmp = ((reg - CB_COLOR8_BASE) / 0x1c) + 8;
15788c2ecf20Sopenharmony_ci		track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
15798c2ecf20Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
15808c2ecf20Sopenharmony_ci		track->cb_color_bo[tmp] = reloc->robj;
15818c2ecf20Sopenharmony_ci		track->cb_dirty = true;
15828c2ecf20Sopenharmony_ci		break;
15838c2ecf20Sopenharmony_ci	case DB_HTILE_DATA_BASE:
15848c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
15858c2ecf20Sopenharmony_ci		if (r) {
15868c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
15878c2ecf20Sopenharmony_ci					"0x%04X\n", reg);
15888c2ecf20Sopenharmony_ci			return -EINVAL;
15898c2ecf20Sopenharmony_ci		}
15908c2ecf20Sopenharmony_ci		track->htile_offset = radeon_get_ib_value(p, idx);
15918c2ecf20Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
15928c2ecf20Sopenharmony_ci		track->htile_bo = reloc->robj;
15938c2ecf20Sopenharmony_ci		track->db_dirty = true;
15948c2ecf20Sopenharmony_ci		break;
15958c2ecf20Sopenharmony_ci	case DB_HTILE_SURFACE:
15968c2ecf20Sopenharmony_ci		/* 8x8 only */
15978c2ecf20Sopenharmony_ci		track->htile_surface = radeon_get_ib_value(p, idx);
15988c2ecf20Sopenharmony_ci		/* force 8x8 htile width and height */
15998c2ecf20Sopenharmony_ci		ib[idx] |= 3;
16008c2ecf20Sopenharmony_ci		track->db_dirty = true;
16018c2ecf20Sopenharmony_ci		break;
16028c2ecf20Sopenharmony_ci	case CB_IMMED0_BASE:
16038c2ecf20Sopenharmony_ci	case CB_IMMED1_BASE:
16048c2ecf20Sopenharmony_ci	case CB_IMMED2_BASE:
16058c2ecf20Sopenharmony_ci	case CB_IMMED3_BASE:
16068c2ecf20Sopenharmony_ci	case CB_IMMED4_BASE:
16078c2ecf20Sopenharmony_ci	case CB_IMMED5_BASE:
16088c2ecf20Sopenharmony_ci	case CB_IMMED6_BASE:
16098c2ecf20Sopenharmony_ci	case CB_IMMED7_BASE:
16108c2ecf20Sopenharmony_ci	case CB_IMMED8_BASE:
16118c2ecf20Sopenharmony_ci	case CB_IMMED9_BASE:
16128c2ecf20Sopenharmony_ci	case CB_IMMED10_BASE:
16138c2ecf20Sopenharmony_ci	case CB_IMMED11_BASE:
16148c2ecf20Sopenharmony_ci	case SQ_PGM_START_FS:
16158c2ecf20Sopenharmony_ci	case SQ_PGM_START_ES:
16168c2ecf20Sopenharmony_ci	case SQ_PGM_START_VS:
16178c2ecf20Sopenharmony_ci	case SQ_PGM_START_GS:
16188c2ecf20Sopenharmony_ci	case SQ_PGM_START_PS:
16198c2ecf20Sopenharmony_ci	case SQ_PGM_START_HS:
16208c2ecf20Sopenharmony_ci	case SQ_PGM_START_LS:
16218c2ecf20Sopenharmony_ci	case SQ_CONST_MEM_BASE:
16228c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_0:
16238c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_1:
16248c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_2:
16258c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_3:
16268c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_4:
16278c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_5:
16288c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_6:
16298c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_7:
16308c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_8:
16318c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_9:
16328c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_10:
16338c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_11:
16348c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_12:
16358c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_13:
16368c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_14:
16378c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_15:
16388c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_0:
16398c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_1:
16408c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_2:
16418c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_3:
16428c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_4:
16438c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_5:
16448c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_6:
16458c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_7:
16468c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_8:
16478c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_9:
16488c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_10:
16498c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_11:
16508c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_12:
16518c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_13:
16528c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_14:
16538c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_15:
16548c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_0:
16558c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_1:
16568c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_2:
16578c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_3:
16588c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_4:
16598c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_5:
16608c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_6:
16618c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_7:
16628c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_8:
16638c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_9:
16648c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_10:
16658c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_11:
16668c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_12:
16678c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_13:
16688c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_14:
16698c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_15:
16708c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_HS_0:
16718c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_HS_1:
16728c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_HS_2:
16738c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_HS_3:
16748c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_HS_4:
16758c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_HS_5:
16768c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_HS_6:
16778c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_HS_7:
16788c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_HS_8:
16798c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_HS_9:
16808c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_HS_10:
16818c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_HS_11:
16828c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_HS_12:
16838c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_HS_13:
16848c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_HS_14:
16858c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_HS_15:
16868c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_LS_0:
16878c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_LS_1:
16888c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_LS_2:
16898c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_LS_3:
16908c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_LS_4:
16918c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_LS_5:
16928c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_LS_6:
16938c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_LS_7:
16948c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_LS_8:
16958c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_LS_9:
16968c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_LS_10:
16978c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_LS_11:
16988c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_LS_12:
16998c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_LS_13:
17008c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_LS_14:
17018c2ecf20Sopenharmony_ci	case SQ_ALU_CONST_CACHE_LS_15:
17028c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
17038c2ecf20Sopenharmony_ci		if (r) {
17048c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
17058c2ecf20Sopenharmony_ci					"0x%04X\n", reg);
17068c2ecf20Sopenharmony_ci			return -EINVAL;
17078c2ecf20Sopenharmony_ci		}
17088c2ecf20Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
17098c2ecf20Sopenharmony_ci		break;
17108c2ecf20Sopenharmony_ci	case SX_MEMORY_EXPORT_BASE:
17118c2ecf20Sopenharmony_ci		if (p->rdev->family >= CHIP_CAYMAN) {
17128c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONFIG_REG "
17138c2ecf20Sopenharmony_ci				 "0x%04X\n", reg);
17148c2ecf20Sopenharmony_ci			return -EINVAL;
17158c2ecf20Sopenharmony_ci		}
17168c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
17178c2ecf20Sopenharmony_ci		if (r) {
17188c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONFIG_REG "
17198c2ecf20Sopenharmony_ci					"0x%04X\n", reg);
17208c2ecf20Sopenharmony_ci			return -EINVAL;
17218c2ecf20Sopenharmony_ci		}
17228c2ecf20Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
17238c2ecf20Sopenharmony_ci		break;
17248c2ecf20Sopenharmony_ci	case CAYMAN_SX_SCATTER_EXPORT_BASE:
17258c2ecf20Sopenharmony_ci		if (p->rdev->family < CHIP_CAYMAN) {
17268c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
17278c2ecf20Sopenharmony_ci				 "0x%04X\n", reg);
17288c2ecf20Sopenharmony_ci			return -EINVAL;
17298c2ecf20Sopenharmony_ci		}
17308c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
17318c2ecf20Sopenharmony_ci		if (r) {
17328c2ecf20Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
17338c2ecf20Sopenharmony_ci					"0x%04X\n", reg);
17348c2ecf20Sopenharmony_ci			return -EINVAL;
17358c2ecf20Sopenharmony_ci		}
17368c2ecf20Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
17378c2ecf20Sopenharmony_ci		break;
17388c2ecf20Sopenharmony_ci	case SX_MISC:
17398c2ecf20Sopenharmony_ci		track->sx_misc_kill_all_prims = (radeon_get_ib_value(p, idx) & 0x1) != 0;
17408c2ecf20Sopenharmony_ci		break;
17418c2ecf20Sopenharmony_ci	default:
17428c2ecf20Sopenharmony_ci		dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
17438c2ecf20Sopenharmony_ci		return -EINVAL;
17448c2ecf20Sopenharmony_ci	}
17458c2ecf20Sopenharmony_ci	return 0;
17468c2ecf20Sopenharmony_ci}
17478c2ecf20Sopenharmony_ci
17488c2ecf20Sopenharmony_ci/**
17498c2ecf20Sopenharmony_ci * evergreen_is_safe_reg() - check if register is authorized or not
17508c2ecf20Sopenharmony_ci * @parser: parser structure holding parsing context
17518c2ecf20Sopenharmony_ci * @reg: register we are testing
17528c2ecf20Sopenharmony_ci *
17538c2ecf20Sopenharmony_ci * This function will test against reg_safe_bm and return true
17548c2ecf20Sopenharmony_ci * if register is safe or false otherwise.
17558c2ecf20Sopenharmony_ci */
17568c2ecf20Sopenharmony_cistatic inline bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg)
17578c2ecf20Sopenharmony_ci{
17588c2ecf20Sopenharmony_ci	struct evergreen_cs_track *track = p->track;
17598c2ecf20Sopenharmony_ci	u32 m, i;
17608c2ecf20Sopenharmony_ci
17618c2ecf20Sopenharmony_ci	i = (reg >> 7);
17628c2ecf20Sopenharmony_ci	if (unlikely(i >= REG_SAFE_BM_SIZE)) {
17638c2ecf20Sopenharmony_ci		return false;
17648c2ecf20Sopenharmony_ci	}
17658c2ecf20Sopenharmony_ci	m = 1 << ((reg >> 2) & 31);
17668c2ecf20Sopenharmony_ci	if (!(track->reg_safe_bm[i] & m))
17678c2ecf20Sopenharmony_ci		return true;
17688c2ecf20Sopenharmony_ci
17698c2ecf20Sopenharmony_ci	return false;
17708c2ecf20Sopenharmony_ci}
17718c2ecf20Sopenharmony_ci
17728c2ecf20Sopenharmony_cistatic int evergreen_packet3_check(struct radeon_cs_parser *p,
17738c2ecf20Sopenharmony_ci				   struct radeon_cs_packet *pkt)
17748c2ecf20Sopenharmony_ci{
17758c2ecf20Sopenharmony_ci	struct radeon_bo_list *reloc;
17768c2ecf20Sopenharmony_ci	struct evergreen_cs_track *track;
17778c2ecf20Sopenharmony_ci	uint32_t *ib;
17788c2ecf20Sopenharmony_ci	unsigned idx;
17798c2ecf20Sopenharmony_ci	unsigned i;
17808c2ecf20Sopenharmony_ci	unsigned start_reg, end_reg, reg;
17818c2ecf20Sopenharmony_ci	int r;
17828c2ecf20Sopenharmony_ci	u32 idx_value;
17838c2ecf20Sopenharmony_ci
17848c2ecf20Sopenharmony_ci	track = (struct evergreen_cs_track *)p->track;
17858c2ecf20Sopenharmony_ci	ib = p->ib.ptr;
17868c2ecf20Sopenharmony_ci	idx = pkt->idx + 1;
17878c2ecf20Sopenharmony_ci	idx_value = radeon_get_ib_value(p, idx);
17888c2ecf20Sopenharmony_ci
17898c2ecf20Sopenharmony_ci	switch (pkt->opcode) {
17908c2ecf20Sopenharmony_ci	case PACKET3_SET_PREDICATION:
17918c2ecf20Sopenharmony_ci	{
17928c2ecf20Sopenharmony_ci		int pred_op;
17938c2ecf20Sopenharmony_ci		int tmp;
17948c2ecf20Sopenharmony_ci		uint64_t offset;
17958c2ecf20Sopenharmony_ci
17968c2ecf20Sopenharmony_ci		if (pkt->count != 1) {
17978c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET PREDICATION\n");
17988c2ecf20Sopenharmony_ci			return -EINVAL;
17998c2ecf20Sopenharmony_ci		}
18008c2ecf20Sopenharmony_ci
18018c2ecf20Sopenharmony_ci		tmp = radeon_get_ib_value(p, idx + 1);
18028c2ecf20Sopenharmony_ci		pred_op = (tmp >> 16) & 0x7;
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ci		/* for the clear predicate operation */
18058c2ecf20Sopenharmony_ci		if (pred_op == 0)
18068c2ecf20Sopenharmony_ci			return 0;
18078c2ecf20Sopenharmony_ci
18088c2ecf20Sopenharmony_ci		if (pred_op > 2) {
18098c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op);
18108c2ecf20Sopenharmony_ci			return -EINVAL;
18118c2ecf20Sopenharmony_ci		}
18128c2ecf20Sopenharmony_ci
18138c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
18148c2ecf20Sopenharmony_ci		if (r) {
18158c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET PREDICATION\n");
18168c2ecf20Sopenharmony_ci			return -EINVAL;
18178c2ecf20Sopenharmony_ci		}
18188c2ecf20Sopenharmony_ci
18198c2ecf20Sopenharmony_ci		offset = reloc->gpu_offset +
18208c2ecf20Sopenharmony_ci			 (idx_value & 0xfffffff0) +
18218c2ecf20Sopenharmony_ci			 ((u64)(tmp & 0xff) << 32);
18228c2ecf20Sopenharmony_ci
18238c2ecf20Sopenharmony_ci		ib[idx + 0] = offset;
18248c2ecf20Sopenharmony_ci		ib[idx + 1] = (tmp & 0xffffff00) | (upper_32_bits(offset) & 0xff);
18258c2ecf20Sopenharmony_ci	}
18268c2ecf20Sopenharmony_ci	break;
18278c2ecf20Sopenharmony_ci	case PACKET3_CONTEXT_CONTROL:
18288c2ecf20Sopenharmony_ci		if (pkt->count != 1) {
18298c2ecf20Sopenharmony_ci			DRM_ERROR("bad CONTEXT_CONTROL\n");
18308c2ecf20Sopenharmony_ci			return -EINVAL;
18318c2ecf20Sopenharmony_ci		}
18328c2ecf20Sopenharmony_ci		break;
18338c2ecf20Sopenharmony_ci	case PACKET3_INDEX_TYPE:
18348c2ecf20Sopenharmony_ci	case PACKET3_NUM_INSTANCES:
18358c2ecf20Sopenharmony_ci	case PACKET3_CLEAR_STATE:
18368c2ecf20Sopenharmony_ci		if (pkt->count) {
18378c2ecf20Sopenharmony_ci			DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");
18388c2ecf20Sopenharmony_ci			return -EINVAL;
18398c2ecf20Sopenharmony_ci		}
18408c2ecf20Sopenharmony_ci		break;
18418c2ecf20Sopenharmony_ci	case CAYMAN_PACKET3_DEALLOC_STATE:
18428c2ecf20Sopenharmony_ci		if (p->rdev->family < CHIP_CAYMAN) {
18438c2ecf20Sopenharmony_ci			DRM_ERROR("bad PACKET3_DEALLOC_STATE\n");
18448c2ecf20Sopenharmony_ci			return -EINVAL;
18458c2ecf20Sopenharmony_ci		}
18468c2ecf20Sopenharmony_ci		if (pkt->count) {
18478c2ecf20Sopenharmony_ci			DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");
18488c2ecf20Sopenharmony_ci			return -EINVAL;
18498c2ecf20Sopenharmony_ci		}
18508c2ecf20Sopenharmony_ci		break;
18518c2ecf20Sopenharmony_ci	case PACKET3_INDEX_BASE:
18528c2ecf20Sopenharmony_ci	{
18538c2ecf20Sopenharmony_ci		uint64_t offset;
18548c2ecf20Sopenharmony_ci
18558c2ecf20Sopenharmony_ci		if (pkt->count != 1) {
18568c2ecf20Sopenharmony_ci			DRM_ERROR("bad INDEX_BASE\n");
18578c2ecf20Sopenharmony_ci			return -EINVAL;
18588c2ecf20Sopenharmony_ci		}
18598c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
18608c2ecf20Sopenharmony_ci		if (r) {
18618c2ecf20Sopenharmony_ci			DRM_ERROR("bad INDEX_BASE\n");
18628c2ecf20Sopenharmony_ci			return -EINVAL;
18638c2ecf20Sopenharmony_ci		}
18648c2ecf20Sopenharmony_ci
18658c2ecf20Sopenharmony_ci		offset = reloc->gpu_offset +
18668c2ecf20Sopenharmony_ci			 idx_value +
18678c2ecf20Sopenharmony_ci			 ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32);
18688c2ecf20Sopenharmony_ci
18698c2ecf20Sopenharmony_ci		ib[idx+0] = offset;
18708c2ecf20Sopenharmony_ci		ib[idx+1] = upper_32_bits(offset) & 0xff;
18718c2ecf20Sopenharmony_ci
18728c2ecf20Sopenharmony_ci		r = evergreen_cs_track_check(p);
18738c2ecf20Sopenharmony_ci		if (r) {
18748c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
18758c2ecf20Sopenharmony_ci			return r;
18768c2ecf20Sopenharmony_ci		}
18778c2ecf20Sopenharmony_ci		break;
18788c2ecf20Sopenharmony_ci	}
18798c2ecf20Sopenharmony_ci	case PACKET3_INDEX_BUFFER_SIZE:
18808c2ecf20Sopenharmony_ci	{
18818c2ecf20Sopenharmony_ci		if (pkt->count != 0) {
18828c2ecf20Sopenharmony_ci			DRM_ERROR("bad INDEX_BUFFER_SIZE\n");
18838c2ecf20Sopenharmony_ci			return -EINVAL;
18848c2ecf20Sopenharmony_ci		}
18858c2ecf20Sopenharmony_ci		break;
18868c2ecf20Sopenharmony_ci	}
18878c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX:
18888c2ecf20Sopenharmony_ci	{
18898c2ecf20Sopenharmony_ci		uint64_t offset;
18908c2ecf20Sopenharmony_ci		if (pkt->count != 3) {
18918c2ecf20Sopenharmony_ci			DRM_ERROR("bad DRAW_INDEX\n");
18928c2ecf20Sopenharmony_ci			return -EINVAL;
18938c2ecf20Sopenharmony_ci		}
18948c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
18958c2ecf20Sopenharmony_ci		if (r) {
18968c2ecf20Sopenharmony_ci			DRM_ERROR("bad DRAW_INDEX\n");
18978c2ecf20Sopenharmony_ci			return -EINVAL;
18988c2ecf20Sopenharmony_ci		}
18998c2ecf20Sopenharmony_ci
19008c2ecf20Sopenharmony_ci		offset = reloc->gpu_offset +
19018c2ecf20Sopenharmony_ci			 idx_value +
19028c2ecf20Sopenharmony_ci			 ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32);
19038c2ecf20Sopenharmony_ci
19048c2ecf20Sopenharmony_ci		ib[idx+0] = offset;
19058c2ecf20Sopenharmony_ci		ib[idx+1] = upper_32_bits(offset) & 0xff;
19068c2ecf20Sopenharmony_ci
19078c2ecf20Sopenharmony_ci		r = evergreen_cs_track_check(p);
19088c2ecf20Sopenharmony_ci		if (r) {
19098c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
19108c2ecf20Sopenharmony_ci			return r;
19118c2ecf20Sopenharmony_ci		}
19128c2ecf20Sopenharmony_ci		break;
19138c2ecf20Sopenharmony_ci	}
19148c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX_2:
19158c2ecf20Sopenharmony_ci	{
19168c2ecf20Sopenharmony_ci		uint64_t offset;
19178c2ecf20Sopenharmony_ci
19188c2ecf20Sopenharmony_ci		if (pkt->count != 4) {
19198c2ecf20Sopenharmony_ci			DRM_ERROR("bad DRAW_INDEX_2\n");
19208c2ecf20Sopenharmony_ci			return -EINVAL;
19218c2ecf20Sopenharmony_ci		}
19228c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
19238c2ecf20Sopenharmony_ci		if (r) {
19248c2ecf20Sopenharmony_ci			DRM_ERROR("bad DRAW_INDEX_2\n");
19258c2ecf20Sopenharmony_ci			return -EINVAL;
19268c2ecf20Sopenharmony_ci		}
19278c2ecf20Sopenharmony_ci
19288c2ecf20Sopenharmony_ci		offset = reloc->gpu_offset +
19298c2ecf20Sopenharmony_ci			 radeon_get_ib_value(p, idx+1) +
19308c2ecf20Sopenharmony_ci			 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
19318c2ecf20Sopenharmony_ci
19328c2ecf20Sopenharmony_ci		ib[idx+1] = offset;
19338c2ecf20Sopenharmony_ci		ib[idx+2] = upper_32_bits(offset) & 0xff;
19348c2ecf20Sopenharmony_ci
19358c2ecf20Sopenharmony_ci		r = evergreen_cs_track_check(p);
19368c2ecf20Sopenharmony_ci		if (r) {
19378c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
19388c2ecf20Sopenharmony_ci			return r;
19398c2ecf20Sopenharmony_ci		}
19408c2ecf20Sopenharmony_ci		break;
19418c2ecf20Sopenharmony_ci	}
19428c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX_AUTO:
19438c2ecf20Sopenharmony_ci		if (pkt->count != 1) {
19448c2ecf20Sopenharmony_ci			DRM_ERROR("bad DRAW_INDEX_AUTO\n");
19458c2ecf20Sopenharmony_ci			return -EINVAL;
19468c2ecf20Sopenharmony_ci		}
19478c2ecf20Sopenharmony_ci		r = evergreen_cs_track_check(p);
19488c2ecf20Sopenharmony_ci		if (r) {
19498c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
19508c2ecf20Sopenharmony_ci			return r;
19518c2ecf20Sopenharmony_ci		}
19528c2ecf20Sopenharmony_ci		break;
19538c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX_MULTI_AUTO:
19548c2ecf20Sopenharmony_ci		if (pkt->count != 2) {
19558c2ecf20Sopenharmony_ci			DRM_ERROR("bad DRAW_INDEX_MULTI_AUTO\n");
19568c2ecf20Sopenharmony_ci			return -EINVAL;
19578c2ecf20Sopenharmony_ci		}
19588c2ecf20Sopenharmony_ci		r = evergreen_cs_track_check(p);
19598c2ecf20Sopenharmony_ci		if (r) {
19608c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
19618c2ecf20Sopenharmony_ci			return r;
19628c2ecf20Sopenharmony_ci		}
19638c2ecf20Sopenharmony_ci		break;
19648c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX_IMMD:
19658c2ecf20Sopenharmony_ci		if (pkt->count < 2) {
19668c2ecf20Sopenharmony_ci			DRM_ERROR("bad DRAW_INDEX_IMMD\n");
19678c2ecf20Sopenharmony_ci			return -EINVAL;
19688c2ecf20Sopenharmony_ci		}
19698c2ecf20Sopenharmony_ci		r = evergreen_cs_track_check(p);
19708c2ecf20Sopenharmony_ci		if (r) {
19718c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
19728c2ecf20Sopenharmony_ci			return r;
19738c2ecf20Sopenharmony_ci		}
19748c2ecf20Sopenharmony_ci		break;
19758c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX_OFFSET:
19768c2ecf20Sopenharmony_ci		if (pkt->count != 2) {
19778c2ecf20Sopenharmony_ci			DRM_ERROR("bad DRAW_INDEX_OFFSET\n");
19788c2ecf20Sopenharmony_ci			return -EINVAL;
19798c2ecf20Sopenharmony_ci		}
19808c2ecf20Sopenharmony_ci		r = evergreen_cs_track_check(p);
19818c2ecf20Sopenharmony_ci		if (r) {
19828c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
19838c2ecf20Sopenharmony_ci			return r;
19848c2ecf20Sopenharmony_ci		}
19858c2ecf20Sopenharmony_ci		break;
19868c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX_OFFSET_2:
19878c2ecf20Sopenharmony_ci		if (pkt->count != 3) {
19888c2ecf20Sopenharmony_ci			DRM_ERROR("bad DRAW_INDEX_OFFSET_2\n");
19898c2ecf20Sopenharmony_ci			return -EINVAL;
19908c2ecf20Sopenharmony_ci		}
19918c2ecf20Sopenharmony_ci		r = evergreen_cs_track_check(p);
19928c2ecf20Sopenharmony_ci		if (r) {
19938c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
19948c2ecf20Sopenharmony_ci			return r;
19958c2ecf20Sopenharmony_ci		}
19968c2ecf20Sopenharmony_ci		break;
19978c2ecf20Sopenharmony_ci	case PACKET3_SET_BASE:
19988c2ecf20Sopenharmony_ci	{
19998c2ecf20Sopenharmony_ci		/*
20008c2ecf20Sopenharmony_ci		DW 1 HEADER Header of the packet. Shader_Type in bit 1 of the Header will correspond to the shader type of the Load, see Type-3 Packet.
20018c2ecf20Sopenharmony_ci		   2 BASE_INDEX Bits [3:0] BASE_INDEX - Base Index specifies which base address is specified in the last two DWs.
20028c2ecf20Sopenharmony_ci		     0001: DX11 Draw_Index_Indirect Patch Table Base: Base address for Draw_Index_Indirect data.
20038c2ecf20Sopenharmony_ci		   3 ADDRESS_LO Bits [31:3] - Lower bits of QWORD-Aligned Address. Bits [2:0] - Reserved
20048c2ecf20Sopenharmony_ci		   4 ADDRESS_HI Bits [31:8] - Reserved. Bits [7:0] - Upper bits of Address [47:32]
20058c2ecf20Sopenharmony_ci		*/
20068c2ecf20Sopenharmony_ci		if (pkt->count != 2) {
20078c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET_BASE\n");
20088c2ecf20Sopenharmony_ci			return -EINVAL;
20098c2ecf20Sopenharmony_ci		}
20108c2ecf20Sopenharmony_ci
20118c2ecf20Sopenharmony_ci		/* currently only supporting setting indirect draw buffer base address */
20128c2ecf20Sopenharmony_ci		if (idx_value != 1) {
20138c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET_BASE\n");
20148c2ecf20Sopenharmony_ci			return -EINVAL;
20158c2ecf20Sopenharmony_ci		}
20168c2ecf20Sopenharmony_ci
20178c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
20188c2ecf20Sopenharmony_ci		if (r) {
20198c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET_BASE\n");
20208c2ecf20Sopenharmony_ci			return -EINVAL;
20218c2ecf20Sopenharmony_ci		}
20228c2ecf20Sopenharmony_ci
20238c2ecf20Sopenharmony_ci		track->indirect_draw_buffer_size = radeon_bo_size(reloc->robj);
20248c2ecf20Sopenharmony_ci
20258c2ecf20Sopenharmony_ci		ib[idx+1] = reloc->gpu_offset;
20268c2ecf20Sopenharmony_ci		ib[idx+2] = upper_32_bits(reloc->gpu_offset) & 0xff;
20278c2ecf20Sopenharmony_ci
20288c2ecf20Sopenharmony_ci		break;
20298c2ecf20Sopenharmony_ci	}
20308c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDIRECT:
20318c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX_INDIRECT:
20328c2ecf20Sopenharmony_ci	{
20338c2ecf20Sopenharmony_ci		u64 size = pkt->opcode == PACKET3_DRAW_INDIRECT ? 16 : 20;
20348c2ecf20Sopenharmony_ci
20358c2ecf20Sopenharmony_ci		/*
20368c2ecf20Sopenharmony_ci		DW 1 HEADER
20378c2ecf20Sopenharmony_ci		   2 DATA_OFFSET Bits [31:0] + byte aligned offset where the required data structure starts. Bits 1:0 are zero
20388c2ecf20Sopenharmony_ci		   3 DRAW_INITIATOR Draw Initiator Register. Written to the VGT_DRAW_INITIATOR register for the assigned context
20398c2ecf20Sopenharmony_ci		*/
20408c2ecf20Sopenharmony_ci		if (pkt->count != 1) {
20418c2ecf20Sopenharmony_ci			DRM_ERROR("bad DRAW_INDIRECT\n");
20428c2ecf20Sopenharmony_ci			return -EINVAL;
20438c2ecf20Sopenharmony_ci		}
20448c2ecf20Sopenharmony_ci
20458c2ecf20Sopenharmony_ci		if (idx_value + size > track->indirect_draw_buffer_size) {
20468c2ecf20Sopenharmony_ci			dev_warn(p->dev, "DRAW_INDIRECT buffer too small %u + %llu > %lu\n",
20478c2ecf20Sopenharmony_ci				idx_value, size, track->indirect_draw_buffer_size);
20488c2ecf20Sopenharmony_ci			return -EINVAL;
20498c2ecf20Sopenharmony_ci		}
20508c2ecf20Sopenharmony_ci
20518c2ecf20Sopenharmony_ci		r = evergreen_cs_track_check(p);
20528c2ecf20Sopenharmony_ci		if (r) {
20538c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
20548c2ecf20Sopenharmony_ci			return r;
20558c2ecf20Sopenharmony_ci		}
20568c2ecf20Sopenharmony_ci		break;
20578c2ecf20Sopenharmony_ci	}
20588c2ecf20Sopenharmony_ci	case PACKET3_DISPATCH_DIRECT:
20598c2ecf20Sopenharmony_ci		if (pkt->count != 3) {
20608c2ecf20Sopenharmony_ci			DRM_ERROR("bad DISPATCH_DIRECT\n");
20618c2ecf20Sopenharmony_ci			return -EINVAL;
20628c2ecf20Sopenharmony_ci		}
20638c2ecf20Sopenharmony_ci		r = evergreen_cs_track_check(p);
20648c2ecf20Sopenharmony_ci		if (r) {
20658c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
20668c2ecf20Sopenharmony_ci			return r;
20678c2ecf20Sopenharmony_ci		}
20688c2ecf20Sopenharmony_ci		break;
20698c2ecf20Sopenharmony_ci	case PACKET3_DISPATCH_INDIRECT:
20708c2ecf20Sopenharmony_ci		if (pkt->count != 1) {
20718c2ecf20Sopenharmony_ci			DRM_ERROR("bad DISPATCH_INDIRECT\n");
20728c2ecf20Sopenharmony_ci			return -EINVAL;
20738c2ecf20Sopenharmony_ci		}
20748c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
20758c2ecf20Sopenharmony_ci		if (r) {
20768c2ecf20Sopenharmony_ci			DRM_ERROR("bad DISPATCH_INDIRECT\n");
20778c2ecf20Sopenharmony_ci			return -EINVAL;
20788c2ecf20Sopenharmony_ci		}
20798c2ecf20Sopenharmony_ci		ib[idx+0] = idx_value + (u32)(reloc->gpu_offset & 0xffffffff);
20808c2ecf20Sopenharmony_ci		r = evergreen_cs_track_check(p);
20818c2ecf20Sopenharmony_ci		if (r) {
20828c2ecf20Sopenharmony_ci			dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
20838c2ecf20Sopenharmony_ci			return r;
20848c2ecf20Sopenharmony_ci		}
20858c2ecf20Sopenharmony_ci		break;
20868c2ecf20Sopenharmony_ci	case PACKET3_WAIT_REG_MEM:
20878c2ecf20Sopenharmony_ci		if (pkt->count != 5) {
20888c2ecf20Sopenharmony_ci			DRM_ERROR("bad WAIT_REG_MEM\n");
20898c2ecf20Sopenharmony_ci			return -EINVAL;
20908c2ecf20Sopenharmony_ci		}
20918c2ecf20Sopenharmony_ci		/* bit 4 is reg (0) or mem (1) */
20928c2ecf20Sopenharmony_ci		if (idx_value & 0x10) {
20938c2ecf20Sopenharmony_ci			uint64_t offset;
20948c2ecf20Sopenharmony_ci
20958c2ecf20Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, 0);
20968c2ecf20Sopenharmony_ci			if (r) {
20978c2ecf20Sopenharmony_ci				DRM_ERROR("bad WAIT_REG_MEM\n");
20988c2ecf20Sopenharmony_ci				return -EINVAL;
20998c2ecf20Sopenharmony_ci			}
21008c2ecf20Sopenharmony_ci
21018c2ecf20Sopenharmony_ci			offset = reloc->gpu_offset +
21028c2ecf20Sopenharmony_ci				 (radeon_get_ib_value(p, idx+1) & 0xfffffffc) +
21038c2ecf20Sopenharmony_ci				 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
21048c2ecf20Sopenharmony_ci
21058c2ecf20Sopenharmony_ci			ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffffc);
21068c2ecf20Sopenharmony_ci			ib[idx+2] = upper_32_bits(offset) & 0xff;
21078c2ecf20Sopenharmony_ci		} else if (idx_value & 0x100) {
21088c2ecf20Sopenharmony_ci			DRM_ERROR("cannot use PFP on REG wait\n");
21098c2ecf20Sopenharmony_ci			return -EINVAL;
21108c2ecf20Sopenharmony_ci		}
21118c2ecf20Sopenharmony_ci		break;
21128c2ecf20Sopenharmony_ci	case PACKET3_CP_DMA:
21138c2ecf20Sopenharmony_ci	{
21148c2ecf20Sopenharmony_ci		u32 command, size, info;
21158c2ecf20Sopenharmony_ci		u64 offset, tmp;
21168c2ecf20Sopenharmony_ci		if (pkt->count != 4) {
21178c2ecf20Sopenharmony_ci			DRM_ERROR("bad CP DMA\n");
21188c2ecf20Sopenharmony_ci			return -EINVAL;
21198c2ecf20Sopenharmony_ci		}
21208c2ecf20Sopenharmony_ci		command = radeon_get_ib_value(p, idx+4);
21218c2ecf20Sopenharmony_ci		size = command & 0x1fffff;
21228c2ecf20Sopenharmony_ci		info = radeon_get_ib_value(p, idx+1);
21238c2ecf20Sopenharmony_ci		if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */
21248c2ecf20Sopenharmony_ci		    (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */
21258c2ecf20Sopenharmony_ci		    ((((info & 0x00300000) >> 20) == 0) &&
21268c2ecf20Sopenharmony_ci		     (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */
21278c2ecf20Sopenharmony_ci		    ((((info & 0x60000000) >> 29) == 0) &&
21288c2ecf20Sopenharmony_ci		     (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */
21298c2ecf20Sopenharmony_ci			/* non mem to mem copies requires dw aligned count */
21308c2ecf20Sopenharmony_ci			if (size % 4) {
21318c2ecf20Sopenharmony_ci				DRM_ERROR("CP DMA command requires dw count alignment\n");
21328c2ecf20Sopenharmony_ci				return -EINVAL;
21338c2ecf20Sopenharmony_ci			}
21348c2ecf20Sopenharmony_ci		}
21358c2ecf20Sopenharmony_ci		if (command & PACKET3_CP_DMA_CMD_SAS) {
21368c2ecf20Sopenharmony_ci			/* src address space is register */
21378c2ecf20Sopenharmony_ci			/* GDS is ok */
21388c2ecf20Sopenharmony_ci			if (((info & 0x60000000) >> 29) != 1) {
21398c2ecf20Sopenharmony_ci				DRM_ERROR("CP DMA SAS not supported\n");
21408c2ecf20Sopenharmony_ci				return -EINVAL;
21418c2ecf20Sopenharmony_ci			}
21428c2ecf20Sopenharmony_ci		} else {
21438c2ecf20Sopenharmony_ci			if (command & PACKET3_CP_DMA_CMD_SAIC) {
21448c2ecf20Sopenharmony_ci				DRM_ERROR("CP DMA SAIC only supported for registers\n");
21458c2ecf20Sopenharmony_ci				return -EINVAL;
21468c2ecf20Sopenharmony_ci			}
21478c2ecf20Sopenharmony_ci			/* src address space is memory */
21488c2ecf20Sopenharmony_ci			if (((info & 0x60000000) >> 29) == 0) {
21498c2ecf20Sopenharmony_ci				r = radeon_cs_packet_next_reloc(p, &reloc, 0);
21508c2ecf20Sopenharmony_ci				if (r) {
21518c2ecf20Sopenharmony_ci					DRM_ERROR("bad CP DMA SRC\n");
21528c2ecf20Sopenharmony_ci					return -EINVAL;
21538c2ecf20Sopenharmony_ci				}
21548c2ecf20Sopenharmony_ci
21558c2ecf20Sopenharmony_ci				tmp = radeon_get_ib_value(p, idx) +
21568c2ecf20Sopenharmony_ci					((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32);
21578c2ecf20Sopenharmony_ci
21588c2ecf20Sopenharmony_ci				offset = reloc->gpu_offset + tmp;
21598c2ecf20Sopenharmony_ci
21608c2ecf20Sopenharmony_ci				if ((tmp + size) > radeon_bo_size(reloc->robj)) {
21618c2ecf20Sopenharmony_ci					dev_warn(p->dev, "CP DMA src buffer too small (%llu %lu)\n",
21628c2ecf20Sopenharmony_ci						 tmp + size, radeon_bo_size(reloc->robj));
21638c2ecf20Sopenharmony_ci					return -EINVAL;
21648c2ecf20Sopenharmony_ci				}
21658c2ecf20Sopenharmony_ci
21668c2ecf20Sopenharmony_ci				ib[idx] = offset;
21678c2ecf20Sopenharmony_ci				ib[idx+1] = (ib[idx+1] & 0xffffff00) | (upper_32_bits(offset) & 0xff);
21688c2ecf20Sopenharmony_ci			} else if (((info & 0x60000000) >> 29) != 2) {
21698c2ecf20Sopenharmony_ci				DRM_ERROR("bad CP DMA SRC_SEL\n");
21708c2ecf20Sopenharmony_ci				return -EINVAL;
21718c2ecf20Sopenharmony_ci			}
21728c2ecf20Sopenharmony_ci		}
21738c2ecf20Sopenharmony_ci		if (command & PACKET3_CP_DMA_CMD_DAS) {
21748c2ecf20Sopenharmony_ci			/* dst address space is register */
21758c2ecf20Sopenharmony_ci			/* GDS is ok */
21768c2ecf20Sopenharmony_ci			if (((info & 0x00300000) >> 20) != 1) {
21778c2ecf20Sopenharmony_ci				DRM_ERROR("CP DMA DAS not supported\n");
21788c2ecf20Sopenharmony_ci				return -EINVAL;
21798c2ecf20Sopenharmony_ci			}
21808c2ecf20Sopenharmony_ci		} else {
21818c2ecf20Sopenharmony_ci			/* dst address space is memory */
21828c2ecf20Sopenharmony_ci			if (command & PACKET3_CP_DMA_CMD_DAIC) {
21838c2ecf20Sopenharmony_ci				DRM_ERROR("CP DMA DAIC only supported for registers\n");
21848c2ecf20Sopenharmony_ci				return -EINVAL;
21858c2ecf20Sopenharmony_ci			}
21868c2ecf20Sopenharmony_ci			if (((info & 0x00300000) >> 20) == 0) {
21878c2ecf20Sopenharmony_ci				r = radeon_cs_packet_next_reloc(p, &reloc, 0);
21888c2ecf20Sopenharmony_ci				if (r) {
21898c2ecf20Sopenharmony_ci					DRM_ERROR("bad CP DMA DST\n");
21908c2ecf20Sopenharmony_ci					return -EINVAL;
21918c2ecf20Sopenharmony_ci				}
21928c2ecf20Sopenharmony_ci
21938c2ecf20Sopenharmony_ci				tmp = radeon_get_ib_value(p, idx+2) +
21948c2ecf20Sopenharmony_ci					((u64)(radeon_get_ib_value(p, idx+3) & 0xff) << 32);
21958c2ecf20Sopenharmony_ci
21968c2ecf20Sopenharmony_ci				offset = reloc->gpu_offset + tmp;
21978c2ecf20Sopenharmony_ci
21988c2ecf20Sopenharmony_ci				if ((tmp + size) > radeon_bo_size(reloc->robj)) {
21998c2ecf20Sopenharmony_ci					dev_warn(p->dev, "CP DMA dst buffer too small (%llu %lu)\n",
22008c2ecf20Sopenharmony_ci						 tmp + size, radeon_bo_size(reloc->robj));
22018c2ecf20Sopenharmony_ci					return -EINVAL;
22028c2ecf20Sopenharmony_ci				}
22038c2ecf20Sopenharmony_ci
22048c2ecf20Sopenharmony_ci				ib[idx+2] = offset;
22058c2ecf20Sopenharmony_ci				ib[idx+3] = upper_32_bits(offset) & 0xff;
22068c2ecf20Sopenharmony_ci			} else {
22078c2ecf20Sopenharmony_ci				DRM_ERROR("bad CP DMA DST_SEL\n");
22088c2ecf20Sopenharmony_ci				return -EINVAL;
22098c2ecf20Sopenharmony_ci			}
22108c2ecf20Sopenharmony_ci		}
22118c2ecf20Sopenharmony_ci		break;
22128c2ecf20Sopenharmony_ci	}
22138c2ecf20Sopenharmony_ci	case PACKET3_PFP_SYNC_ME:
22148c2ecf20Sopenharmony_ci		if (pkt->count) {
22158c2ecf20Sopenharmony_ci			DRM_ERROR("bad PFP_SYNC_ME\n");
22168c2ecf20Sopenharmony_ci			return -EINVAL;
22178c2ecf20Sopenharmony_ci		}
22188c2ecf20Sopenharmony_ci		break;
22198c2ecf20Sopenharmony_ci	case PACKET3_SURFACE_SYNC:
22208c2ecf20Sopenharmony_ci		if (pkt->count != 3) {
22218c2ecf20Sopenharmony_ci			DRM_ERROR("bad SURFACE_SYNC\n");
22228c2ecf20Sopenharmony_ci			return -EINVAL;
22238c2ecf20Sopenharmony_ci		}
22248c2ecf20Sopenharmony_ci		/* 0xffffffff/0x0 is flush all cache flag */
22258c2ecf20Sopenharmony_ci		if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
22268c2ecf20Sopenharmony_ci		    radeon_get_ib_value(p, idx + 2) != 0) {
22278c2ecf20Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, 0);
22288c2ecf20Sopenharmony_ci			if (r) {
22298c2ecf20Sopenharmony_ci				DRM_ERROR("bad SURFACE_SYNC\n");
22308c2ecf20Sopenharmony_ci				return -EINVAL;
22318c2ecf20Sopenharmony_ci			}
22328c2ecf20Sopenharmony_ci			ib[idx+2] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
22338c2ecf20Sopenharmony_ci		}
22348c2ecf20Sopenharmony_ci		break;
22358c2ecf20Sopenharmony_ci	case PACKET3_EVENT_WRITE:
22368c2ecf20Sopenharmony_ci		if (pkt->count != 2 && pkt->count != 0) {
22378c2ecf20Sopenharmony_ci			DRM_ERROR("bad EVENT_WRITE\n");
22388c2ecf20Sopenharmony_ci			return -EINVAL;
22398c2ecf20Sopenharmony_ci		}
22408c2ecf20Sopenharmony_ci		if (pkt->count) {
22418c2ecf20Sopenharmony_ci			uint64_t offset;
22428c2ecf20Sopenharmony_ci
22438c2ecf20Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, 0);
22448c2ecf20Sopenharmony_ci			if (r) {
22458c2ecf20Sopenharmony_ci				DRM_ERROR("bad EVENT_WRITE\n");
22468c2ecf20Sopenharmony_ci				return -EINVAL;
22478c2ecf20Sopenharmony_ci			}
22488c2ecf20Sopenharmony_ci			offset = reloc->gpu_offset +
22498c2ecf20Sopenharmony_ci				 (radeon_get_ib_value(p, idx+1) & 0xfffffff8) +
22508c2ecf20Sopenharmony_ci				 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
22518c2ecf20Sopenharmony_ci
22528c2ecf20Sopenharmony_ci			ib[idx+1] = offset & 0xfffffff8;
22538c2ecf20Sopenharmony_ci			ib[idx+2] = upper_32_bits(offset) & 0xff;
22548c2ecf20Sopenharmony_ci		}
22558c2ecf20Sopenharmony_ci		break;
22568c2ecf20Sopenharmony_ci	case PACKET3_EVENT_WRITE_EOP:
22578c2ecf20Sopenharmony_ci	{
22588c2ecf20Sopenharmony_ci		uint64_t offset;
22598c2ecf20Sopenharmony_ci
22608c2ecf20Sopenharmony_ci		if (pkt->count != 4) {
22618c2ecf20Sopenharmony_ci			DRM_ERROR("bad EVENT_WRITE_EOP\n");
22628c2ecf20Sopenharmony_ci			return -EINVAL;
22638c2ecf20Sopenharmony_ci		}
22648c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
22658c2ecf20Sopenharmony_ci		if (r) {
22668c2ecf20Sopenharmony_ci			DRM_ERROR("bad EVENT_WRITE_EOP\n");
22678c2ecf20Sopenharmony_ci			return -EINVAL;
22688c2ecf20Sopenharmony_ci		}
22698c2ecf20Sopenharmony_ci
22708c2ecf20Sopenharmony_ci		offset = reloc->gpu_offset +
22718c2ecf20Sopenharmony_ci			 (radeon_get_ib_value(p, idx+1) & 0xfffffffc) +
22728c2ecf20Sopenharmony_ci			 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
22738c2ecf20Sopenharmony_ci
22748c2ecf20Sopenharmony_ci		ib[idx+1] = offset & 0xfffffffc;
22758c2ecf20Sopenharmony_ci		ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff);
22768c2ecf20Sopenharmony_ci		break;
22778c2ecf20Sopenharmony_ci	}
22788c2ecf20Sopenharmony_ci	case PACKET3_EVENT_WRITE_EOS:
22798c2ecf20Sopenharmony_ci	{
22808c2ecf20Sopenharmony_ci		uint64_t offset;
22818c2ecf20Sopenharmony_ci
22828c2ecf20Sopenharmony_ci		if (pkt->count != 3) {
22838c2ecf20Sopenharmony_ci			DRM_ERROR("bad EVENT_WRITE_EOS\n");
22848c2ecf20Sopenharmony_ci			return -EINVAL;
22858c2ecf20Sopenharmony_ci		}
22868c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
22878c2ecf20Sopenharmony_ci		if (r) {
22888c2ecf20Sopenharmony_ci			DRM_ERROR("bad EVENT_WRITE_EOS\n");
22898c2ecf20Sopenharmony_ci			return -EINVAL;
22908c2ecf20Sopenharmony_ci		}
22918c2ecf20Sopenharmony_ci
22928c2ecf20Sopenharmony_ci		offset = reloc->gpu_offset +
22938c2ecf20Sopenharmony_ci			 (radeon_get_ib_value(p, idx+1) & 0xfffffffc) +
22948c2ecf20Sopenharmony_ci			 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
22958c2ecf20Sopenharmony_ci
22968c2ecf20Sopenharmony_ci		ib[idx+1] = offset & 0xfffffffc;
22978c2ecf20Sopenharmony_ci		ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff);
22988c2ecf20Sopenharmony_ci		break;
22998c2ecf20Sopenharmony_ci	}
23008c2ecf20Sopenharmony_ci	case PACKET3_SET_CONFIG_REG:
23018c2ecf20Sopenharmony_ci		start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START;
23028c2ecf20Sopenharmony_ci		end_reg = 4 * pkt->count + start_reg - 4;
23038c2ecf20Sopenharmony_ci		if ((start_reg < PACKET3_SET_CONFIG_REG_START) ||
23048c2ecf20Sopenharmony_ci		    (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
23058c2ecf20Sopenharmony_ci		    (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
23068c2ecf20Sopenharmony_ci			DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
23078c2ecf20Sopenharmony_ci			return -EINVAL;
23088c2ecf20Sopenharmony_ci		}
23098c2ecf20Sopenharmony_ci		for (reg = start_reg, idx++; reg <= end_reg; reg += 4, idx++) {
23108c2ecf20Sopenharmony_ci			if (evergreen_is_safe_reg(p, reg))
23118c2ecf20Sopenharmony_ci				continue;
23128c2ecf20Sopenharmony_ci			r = evergreen_cs_handle_reg(p, reg, idx);
23138c2ecf20Sopenharmony_ci			if (r)
23148c2ecf20Sopenharmony_ci				return r;
23158c2ecf20Sopenharmony_ci		}
23168c2ecf20Sopenharmony_ci		break;
23178c2ecf20Sopenharmony_ci	case PACKET3_SET_CONTEXT_REG:
23188c2ecf20Sopenharmony_ci		start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_START;
23198c2ecf20Sopenharmony_ci		end_reg = 4 * pkt->count + start_reg - 4;
23208c2ecf20Sopenharmony_ci		if ((start_reg < PACKET3_SET_CONTEXT_REG_START) ||
23218c2ecf20Sopenharmony_ci		    (start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
23228c2ecf20Sopenharmony_ci		    (end_reg >= PACKET3_SET_CONTEXT_REG_END)) {
23238c2ecf20Sopenharmony_ci			DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");
23248c2ecf20Sopenharmony_ci			return -EINVAL;
23258c2ecf20Sopenharmony_ci		}
23268c2ecf20Sopenharmony_ci		for (reg = start_reg, idx++; reg <= end_reg; reg += 4, idx++) {
23278c2ecf20Sopenharmony_ci			if (evergreen_is_safe_reg(p, reg))
23288c2ecf20Sopenharmony_ci				continue;
23298c2ecf20Sopenharmony_ci			r = evergreen_cs_handle_reg(p, reg, idx);
23308c2ecf20Sopenharmony_ci			if (r)
23318c2ecf20Sopenharmony_ci				return r;
23328c2ecf20Sopenharmony_ci		}
23338c2ecf20Sopenharmony_ci		break;
23348c2ecf20Sopenharmony_ci	case PACKET3_SET_RESOURCE:
23358c2ecf20Sopenharmony_ci		if (pkt->count % 8) {
23368c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET_RESOURCE\n");
23378c2ecf20Sopenharmony_ci			return -EINVAL;
23388c2ecf20Sopenharmony_ci		}
23398c2ecf20Sopenharmony_ci		start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_START;
23408c2ecf20Sopenharmony_ci		end_reg = 4 * pkt->count + start_reg - 4;
23418c2ecf20Sopenharmony_ci		if ((start_reg < PACKET3_SET_RESOURCE_START) ||
23428c2ecf20Sopenharmony_ci		    (start_reg >= PACKET3_SET_RESOURCE_END) ||
23438c2ecf20Sopenharmony_ci		    (end_reg >= PACKET3_SET_RESOURCE_END)) {
23448c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET_RESOURCE\n");
23458c2ecf20Sopenharmony_ci			return -EINVAL;
23468c2ecf20Sopenharmony_ci		}
23478c2ecf20Sopenharmony_ci		for (i = 0; i < (pkt->count / 8); i++) {
23488c2ecf20Sopenharmony_ci			struct radeon_bo *texture, *mipmap;
23498c2ecf20Sopenharmony_ci			u32 toffset, moffset;
23508c2ecf20Sopenharmony_ci			u32 size, offset, mip_address, tex_dim;
23518c2ecf20Sopenharmony_ci
23528c2ecf20Sopenharmony_ci			switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) {
23538c2ecf20Sopenharmony_ci			case SQ_TEX_VTX_VALID_TEXTURE:
23548c2ecf20Sopenharmony_ci				/* tex base */
23558c2ecf20Sopenharmony_ci				r = radeon_cs_packet_next_reloc(p, &reloc, 0);
23568c2ecf20Sopenharmony_ci				if (r) {
23578c2ecf20Sopenharmony_ci					DRM_ERROR("bad SET_RESOURCE (tex)\n");
23588c2ecf20Sopenharmony_ci					return -EINVAL;
23598c2ecf20Sopenharmony_ci				}
23608c2ecf20Sopenharmony_ci				if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
23618c2ecf20Sopenharmony_ci					ib[idx+1+(i*8)+1] |=
23628c2ecf20Sopenharmony_ci						TEX_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags));
23638c2ecf20Sopenharmony_ci					if (reloc->tiling_flags & RADEON_TILING_MACRO) {
23648c2ecf20Sopenharmony_ci						unsigned bankw, bankh, mtaspect, tile_split;
23658c2ecf20Sopenharmony_ci
23668c2ecf20Sopenharmony_ci						evergreen_tiling_fields(reloc->tiling_flags,
23678c2ecf20Sopenharmony_ci									&bankw, &bankh, &mtaspect,
23688c2ecf20Sopenharmony_ci									&tile_split);
23698c2ecf20Sopenharmony_ci						ib[idx+1+(i*8)+6] |= TEX_TILE_SPLIT(tile_split);
23708c2ecf20Sopenharmony_ci						ib[idx+1+(i*8)+7] |=
23718c2ecf20Sopenharmony_ci							TEX_BANK_WIDTH(bankw) |
23728c2ecf20Sopenharmony_ci							TEX_BANK_HEIGHT(bankh) |
23738c2ecf20Sopenharmony_ci							MACRO_TILE_ASPECT(mtaspect) |
23748c2ecf20Sopenharmony_ci							TEX_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
23758c2ecf20Sopenharmony_ci					}
23768c2ecf20Sopenharmony_ci				}
23778c2ecf20Sopenharmony_ci				texture = reloc->robj;
23788c2ecf20Sopenharmony_ci				toffset = (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
23798c2ecf20Sopenharmony_ci
23808c2ecf20Sopenharmony_ci				/* tex mip base */
23818c2ecf20Sopenharmony_ci				tex_dim = ib[idx+1+(i*8)+0] & 0x7;
23828c2ecf20Sopenharmony_ci				mip_address = ib[idx+1+(i*8)+3];
23838c2ecf20Sopenharmony_ci
23848c2ecf20Sopenharmony_ci				if ((tex_dim == SQ_TEX_DIM_2D_MSAA || tex_dim == SQ_TEX_DIM_2D_ARRAY_MSAA) &&
23858c2ecf20Sopenharmony_ci				    !mip_address &&
23868c2ecf20Sopenharmony_ci				    !radeon_cs_packet_next_is_pkt3_nop(p)) {
23878c2ecf20Sopenharmony_ci					/* MIP_ADDRESS should point to FMASK for an MSAA texture.
23888c2ecf20Sopenharmony_ci					 * It should be 0 if FMASK is disabled. */
23898c2ecf20Sopenharmony_ci					moffset = 0;
23908c2ecf20Sopenharmony_ci					mipmap = NULL;
23918c2ecf20Sopenharmony_ci				} else {
23928c2ecf20Sopenharmony_ci					r = radeon_cs_packet_next_reloc(p, &reloc, 0);
23938c2ecf20Sopenharmony_ci					if (r) {
23948c2ecf20Sopenharmony_ci						DRM_ERROR("bad SET_RESOURCE (tex)\n");
23958c2ecf20Sopenharmony_ci						return -EINVAL;
23968c2ecf20Sopenharmony_ci					}
23978c2ecf20Sopenharmony_ci					moffset = (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
23988c2ecf20Sopenharmony_ci					mipmap = reloc->robj;
23998c2ecf20Sopenharmony_ci				}
24008c2ecf20Sopenharmony_ci
24018c2ecf20Sopenharmony_ci				r = evergreen_cs_track_validate_texture(p, texture, mipmap, idx+1+(i*8));
24028c2ecf20Sopenharmony_ci				if (r)
24038c2ecf20Sopenharmony_ci					return r;
24048c2ecf20Sopenharmony_ci				ib[idx+1+(i*8)+2] += toffset;
24058c2ecf20Sopenharmony_ci				ib[idx+1+(i*8)+3] += moffset;
24068c2ecf20Sopenharmony_ci				break;
24078c2ecf20Sopenharmony_ci			case SQ_TEX_VTX_VALID_BUFFER:
24088c2ecf20Sopenharmony_ci			{
24098c2ecf20Sopenharmony_ci				uint64_t offset64;
24108c2ecf20Sopenharmony_ci				/* vtx base */
24118c2ecf20Sopenharmony_ci				r = radeon_cs_packet_next_reloc(p, &reloc, 0);
24128c2ecf20Sopenharmony_ci				if (r) {
24138c2ecf20Sopenharmony_ci					DRM_ERROR("bad SET_RESOURCE (vtx)\n");
24148c2ecf20Sopenharmony_ci					return -EINVAL;
24158c2ecf20Sopenharmony_ci				}
24168c2ecf20Sopenharmony_ci				offset = radeon_get_ib_value(p, idx+1+(i*8)+0);
24178c2ecf20Sopenharmony_ci				size = radeon_get_ib_value(p, idx+1+(i*8)+1);
24188c2ecf20Sopenharmony_ci				if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
24198c2ecf20Sopenharmony_ci					/* force size to size of the buffer */
24208c2ecf20Sopenharmony_ci					dev_warn_ratelimited(p->dev, "vbo resource seems too big for the bo\n");
24218c2ecf20Sopenharmony_ci					ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj) - offset;
24228c2ecf20Sopenharmony_ci				}
24238c2ecf20Sopenharmony_ci
24248c2ecf20Sopenharmony_ci				offset64 = reloc->gpu_offset + offset;
24258c2ecf20Sopenharmony_ci				ib[idx+1+(i*8)+0] = offset64;
24268c2ecf20Sopenharmony_ci				ib[idx+1+(i*8)+2] = (ib[idx+1+(i*8)+2] & 0xffffff00) |
24278c2ecf20Sopenharmony_ci						    (upper_32_bits(offset64) & 0xff);
24288c2ecf20Sopenharmony_ci				break;
24298c2ecf20Sopenharmony_ci			}
24308c2ecf20Sopenharmony_ci			case SQ_TEX_VTX_INVALID_TEXTURE:
24318c2ecf20Sopenharmony_ci			case SQ_TEX_VTX_INVALID_BUFFER:
24328c2ecf20Sopenharmony_ci			default:
24338c2ecf20Sopenharmony_ci				DRM_ERROR("bad SET_RESOURCE\n");
24348c2ecf20Sopenharmony_ci				return -EINVAL;
24358c2ecf20Sopenharmony_ci			}
24368c2ecf20Sopenharmony_ci		}
24378c2ecf20Sopenharmony_ci		break;
24388c2ecf20Sopenharmony_ci	case PACKET3_SET_ALU_CONST:
24398c2ecf20Sopenharmony_ci		/* XXX fix me ALU const buffers only */
24408c2ecf20Sopenharmony_ci		break;
24418c2ecf20Sopenharmony_ci	case PACKET3_SET_BOOL_CONST:
24428c2ecf20Sopenharmony_ci		start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_START;
24438c2ecf20Sopenharmony_ci		end_reg = 4 * pkt->count + start_reg - 4;
24448c2ecf20Sopenharmony_ci		if ((start_reg < PACKET3_SET_BOOL_CONST_START) ||
24458c2ecf20Sopenharmony_ci		    (start_reg >= PACKET3_SET_BOOL_CONST_END) ||
24468c2ecf20Sopenharmony_ci		    (end_reg >= PACKET3_SET_BOOL_CONST_END)) {
24478c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET_BOOL_CONST\n");
24488c2ecf20Sopenharmony_ci			return -EINVAL;
24498c2ecf20Sopenharmony_ci		}
24508c2ecf20Sopenharmony_ci		break;
24518c2ecf20Sopenharmony_ci	case PACKET3_SET_LOOP_CONST:
24528c2ecf20Sopenharmony_ci		start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_START;
24538c2ecf20Sopenharmony_ci		end_reg = 4 * pkt->count + start_reg - 4;
24548c2ecf20Sopenharmony_ci		if ((start_reg < PACKET3_SET_LOOP_CONST_START) ||
24558c2ecf20Sopenharmony_ci		    (start_reg >= PACKET3_SET_LOOP_CONST_END) ||
24568c2ecf20Sopenharmony_ci		    (end_reg >= PACKET3_SET_LOOP_CONST_END)) {
24578c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET_LOOP_CONST\n");
24588c2ecf20Sopenharmony_ci			return -EINVAL;
24598c2ecf20Sopenharmony_ci		}
24608c2ecf20Sopenharmony_ci		break;
24618c2ecf20Sopenharmony_ci	case PACKET3_SET_CTL_CONST:
24628c2ecf20Sopenharmony_ci		start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_START;
24638c2ecf20Sopenharmony_ci		end_reg = 4 * pkt->count + start_reg - 4;
24648c2ecf20Sopenharmony_ci		if ((start_reg < PACKET3_SET_CTL_CONST_START) ||
24658c2ecf20Sopenharmony_ci		    (start_reg >= PACKET3_SET_CTL_CONST_END) ||
24668c2ecf20Sopenharmony_ci		    (end_reg >= PACKET3_SET_CTL_CONST_END)) {
24678c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET_CTL_CONST\n");
24688c2ecf20Sopenharmony_ci			return -EINVAL;
24698c2ecf20Sopenharmony_ci		}
24708c2ecf20Sopenharmony_ci		break;
24718c2ecf20Sopenharmony_ci	case PACKET3_SET_SAMPLER:
24728c2ecf20Sopenharmony_ci		if (pkt->count % 3) {
24738c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET_SAMPLER\n");
24748c2ecf20Sopenharmony_ci			return -EINVAL;
24758c2ecf20Sopenharmony_ci		}
24768c2ecf20Sopenharmony_ci		start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_START;
24778c2ecf20Sopenharmony_ci		end_reg = 4 * pkt->count + start_reg - 4;
24788c2ecf20Sopenharmony_ci		if ((start_reg < PACKET3_SET_SAMPLER_START) ||
24798c2ecf20Sopenharmony_ci		    (start_reg >= PACKET3_SET_SAMPLER_END) ||
24808c2ecf20Sopenharmony_ci		    (end_reg >= PACKET3_SET_SAMPLER_END)) {
24818c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET_SAMPLER\n");
24828c2ecf20Sopenharmony_ci			return -EINVAL;
24838c2ecf20Sopenharmony_ci		}
24848c2ecf20Sopenharmony_ci		break;
24858c2ecf20Sopenharmony_ci	case PACKET3_STRMOUT_BUFFER_UPDATE:
24868c2ecf20Sopenharmony_ci		if (pkt->count != 4) {
24878c2ecf20Sopenharmony_ci			DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
24888c2ecf20Sopenharmony_ci			return -EINVAL;
24898c2ecf20Sopenharmony_ci		}
24908c2ecf20Sopenharmony_ci		/* Updating memory at DST_ADDRESS. */
24918c2ecf20Sopenharmony_ci		if (idx_value & 0x1) {
24928c2ecf20Sopenharmony_ci			u64 offset;
24938c2ecf20Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, 0);
24948c2ecf20Sopenharmony_ci			if (r) {
24958c2ecf20Sopenharmony_ci				DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n");
24968c2ecf20Sopenharmony_ci				return -EINVAL;
24978c2ecf20Sopenharmony_ci			}
24988c2ecf20Sopenharmony_ci			offset = radeon_get_ib_value(p, idx+1);
24998c2ecf20Sopenharmony_ci			offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
25008c2ecf20Sopenharmony_ci			if ((offset + 4) > radeon_bo_size(reloc->robj)) {
25018c2ecf20Sopenharmony_ci				DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%llx, 0x%lx\n",
25028c2ecf20Sopenharmony_ci					  offset + 4, radeon_bo_size(reloc->robj));
25038c2ecf20Sopenharmony_ci				return -EINVAL;
25048c2ecf20Sopenharmony_ci			}
25058c2ecf20Sopenharmony_ci			offset += reloc->gpu_offset;
25068c2ecf20Sopenharmony_ci			ib[idx+1] = offset;
25078c2ecf20Sopenharmony_ci			ib[idx+2] = upper_32_bits(offset) & 0xff;
25088c2ecf20Sopenharmony_ci		}
25098c2ecf20Sopenharmony_ci		/* Reading data from SRC_ADDRESS. */
25108c2ecf20Sopenharmony_ci		if (((idx_value >> 1) & 0x3) == 2) {
25118c2ecf20Sopenharmony_ci			u64 offset;
25128c2ecf20Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, 0);
25138c2ecf20Sopenharmony_ci			if (r) {
25148c2ecf20Sopenharmony_ci				DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n");
25158c2ecf20Sopenharmony_ci				return -EINVAL;
25168c2ecf20Sopenharmony_ci			}
25178c2ecf20Sopenharmony_ci			offset = radeon_get_ib_value(p, idx+3);
25188c2ecf20Sopenharmony_ci			offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
25198c2ecf20Sopenharmony_ci			if ((offset + 4) > radeon_bo_size(reloc->robj)) {
25208c2ecf20Sopenharmony_ci				DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%llx, 0x%lx\n",
25218c2ecf20Sopenharmony_ci					  offset + 4, radeon_bo_size(reloc->robj));
25228c2ecf20Sopenharmony_ci				return -EINVAL;
25238c2ecf20Sopenharmony_ci			}
25248c2ecf20Sopenharmony_ci			offset += reloc->gpu_offset;
25258c2ecf20Sopenharmony_ci			ib[idx+3] = offset;
25268c2ecf20Sopenharmony_ci			ib[idx+4] = upper_32_bits(offset) & 0xff;
25278c2ecf20Sopenharmony_ci		}
25288c2ecf20Sopenharmony_ci		break;
25298c2ecf20Sopenharmony_ci	case PACKET3_MEM_WRITE:
25308c2ecf20Sopenharmony_ci	{
25318c2ecf20Sopenharmony_ci		u64 offset;
25328c2ecf20Sopenharmony_ci
25338c2ecf20Sopenharmony_ci		if (pkt->count != 3) {
25348c2ecf20Sopenharmony_ci			DRM_ERROR("bad MEM_WRITE (invalid count)\n");
25358c2ecf20Sopenharmony_ci			return -EINVAL;
25368c2ecf20Sopenharmony_ci		}
25378c2ecf20Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
25388c2ecf20Sopenharmony_ci		if (r) {
25398c2ecf20Sopenharmony_ci			DRM_ERROR("bad MEM_WRITE (missing reloc)\n");
25408c2ecf20Sopenharmony_ci			return -EINVAL;
25418c2ecf20Sopenharmony_ci		}
25428c2ecf20Sopenharmony_ci		offset = radeon_get_ib_value(p, idx+0);
25438c2ecf20Sopenharmony_ci		offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL;
25448c2ecf20Sopenharmony_ci		if (offset & 0x7) {
25458c2ecf20Sopenharmony_ci			DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n");
25468c2ecf20Sopenharmony_ci			return -EINVAL;
25478c2ecf20Sopenharmony_ci		}
25488c2ecf20Sopenharmony_ci		if ((offset + 8) > radeon_bo_size(reloc->robj)) {
25498c2ecf20Sopenharmony_ci			DRM_ERROR("bad MEM_WRITE bo too small: 0x%llx, 0x%lx\n",
25508c2ecf20Sopenharmony_ci				  offset + 8, radeon_bo_size(reloc->robj));
25518c2ecf20Sopenharmony_ci			return -EINVAL;
25528c2ecf20Sopenharmony_ci		}
25538c2ecf20Sopenharmony_ci		offset += reloc->gpu_offset;
25548c2ecf20Sopenharmony_ci		ib[idx+0] = offset;
25558c2ecf20Sopenharmony_ci		ib[idx+1] = upper_32_bits(offset) & 0xff;
25568c2ecf20Sopenharmony_ci		break;
25578c2ecf20Sopenharmony_ci	}
25588c2ecf20Sopenharmony_ci	case PACKET3_COPY_DW:
25598c2ecf20Sopenharmony_ci		if (pkt->count != 4) {
25608c2ecf20Sopenharmony_ci			DRM_ERROR("bad COPY_DW (invalid count)\n");
25618c2ecf20Sopenharmony_ci			return -EINVAL;
25628c2ecf20Sopenharmony_ci		}
25638c2ecf20Sopenharmony_ci		if (idx_value & 0x1) {
25648c2ecf20Sopenharmony_ci			u64 offset;
25658c2ecf20Sopenharmony_ci			/* SRC is memory. */
25668c2ecf20Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, 0);
25678c2ecf20Sopenharmony_ci			if (r) {
25688c2ecf20Sopenharmony_ci				DRM_ERROR("bad COPY_DW (missing src reloc)\n");
25698c2ecf20Sopenharmony_ci				return -EINVAL;
25708c2ecf20Sopenharmony_ci			}
25718c2ecf20Sopenharmony_ci			offset = radeon_get_ib_value(p, idx+1);
25728c2ecf20Sopenharmony_ci			offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
25738c2ecf20Sopenharmony_ci			if ((offset + 4) > radeon_bo_size(reloc->robj)) {
25748c2ecf20Sopenharmony_ci				DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n",
25758c2ecf20Sopenharmony_ci					  offset + 4, radeon_bo_size(reloc->robj));
25768c2ecf20Sopenharmony_ci				return -EINVAL;
25778c2ecf20Sopenharmony_ci			}
25788c2ecf20Sopenharmony_ci			offset += reloc->gpu_offset;
25798c2ecf20Sopenharmony_ci			ib[idx+1] = offset;
25808c2ecf20Sopenharmony_ci			ib[idx+2] = upper_32_bits(offset) & 0xff;
25818c2ecf20Sopenharmony_ci		} else {
25828c2ecf20Sopenharmony_ci			/* SRC is a reg. */
25838c2ecf20Sopenharmony_ci			reg = radeon_get_ib_value(p, idx+1) << 2;
25848c2ecf20Sopenharmony_ci			if (!evergreen_is_safe_reg(p, reg)) {
25858c2ecf20Sopenharmony_ci				dev_warn(p->dev, "forbidden register 0x%08x at %d\n",
25868c2ecf20Sopenharmony_ci					 reg, idx + 1);
25878c2ecf20Sopenharmony_ci				return -EINVAL;
25888c2ecf20Sopenharmony_ci			}
25898c2ecf20Sopenharmony_ci		}
25908c2ecf20Sopenharmony_ci		if (idx_value & 0x2) {
25918c2ecf20Sopenharmony_ci			u64 offset;
25928c2ecf20Sopenharmony_ci			/* DST is memory. */
25938c2ecf20Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, 0);
25948c2ecf20Sopenharmony_ci			if (r) {
25958c2ecf20Sopenharmony_ci				DRM_ERROR("bad COPY_DW (missing dst reloc)\n");
25968c2ecf20Sopenharmony_ci				return -EINVAL;
25978c2ecf20Sopenharmony_ci			}
25988c2ecf20Sopenharmony_ci			offset = radeon_get_ib_value(p, idx+3);
25998c2ecf20Sopenharmony_ci			offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
26008c2ecf20Sopenharmony_ci			if ((offset + 4) > radeon_bo_size(reloc->robj)) {
26018c2ecf20Sopenharmony_ci				DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n",
26028c2ecf20Sopenharmony_ci					  offset + 4, radeon_bo_size(reloc->robj));
26038c2ecf20Sopenharmony_ci				return -EINVAL;
26048c2ecf20Sopenharmony_ci			}
26058c2ecf20Sopenharmony_ci			offset += reloc->gpu_offset;
26068c2ecf20Sopenharmony_ci			ib[idx+3] = offset;
26078c2ecf20Sopenharmony_ci			ib[idx+4] = upper_32_bits(offset) & 0xff;
26088c2ecf20Sopenharmony_ci		} else {
26098c2ecf20Sopenharmony_ci			/* DST is a reg. */
26108c2ecf20Sopenharmony_ci			reg = radeon_get_ib_value(p, idx+3) << 2;
26118c2ecf20Sopenharmony_ci			if (!evergreen_is_safe_reg(p, reg)) {
26128c2ecf20Sopenharmony_ci				dev_warn(p->dev, "forbidden register 0x%08x at %d\n",
26138c2ecf20Sopenharmony_ci					 reg, idx + 3);
26148c2ecf20Sopenharmony_ci				return -EINVAL;
26158c2ecf20Sopenharmony_ci			}
26168c2ecf20Sopenharmony_ci		}
26178c2ecf20Sopenharmony_ci		break;
26188c2ecf20Sopenharmony_ci	case PACKET3_SET_APPEND_CNT:
26198c2ecf20Sopenharmony_ci	{
26208c2ecf20Sopenharmony_ci		uint32_t areg;
26218c2ecf20Sopenharmony_ci		uint32_t allowed_reg_base;
26228c2ecf20Sopenharmony_ci		uint32_t source_sel;
26238c2ecf20Sopenharmony_ci		if (pkt->count != 2) {
26248c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET_APPEND_CNT (invalid count)\n");
26258c2ecf20Sopenharmony_ci			return -EINVAL;
26268c2ecf20Sopenharmony_ci		}
26278c2ecf20Sopenharmony_ci
26288c2ecf20Sopenharmony_ci		allowed_reg_base = GDS_APPEND_COUNT_0;
26298c2ecf20Sopenharmony_ci		allowed_reg_base -= PACKET3_SET_CONTEXT_REG_START;
26308c2ecf20Sopenharmony_ci		allowed_reg_base >>= 2;
26318c2ecf20Sopenharmony_ci
26328c2ecf20Sopenharmony_ci		areg = idx_value >> 16;
26338c2ecf20Sopenharmony_ci		if (areg < allowed_reg_base || areg > (allowed_reg_base + 11)) {
26348c2ecf20Sopenharmony_ci			dev_warn(p->dev, "forbidden register for append cnt 0x%08x at %d\n",
26358c2ecf20Sopenharmony_ci				 areg, idx);
26368c2ecf20Sopenharmony_ci			return -EINVAL;
26378c2ecf20Sopenharmony_ci		}
26388c2ecf20Sopenharmony_ci
26398c2ecf20Sopenharmony_ci		source_sel = G_PACKET3_SET_APPEND_CNT_SRC_SELECT(idx_value);
26408c2ecf20Sopenharmony_ci		if (source_sel == PACKET3_SAC_SRC_SEL_MEM) {
26418c2ecf20Sopenharmony_ci			uint64_t offset;
26428c2ecf20Sopenharmony_ci			uint32_t swap;
26438c2ecf20Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, 0);
26448c2ecf20Sopenharmony_ci			if (r) {
26458c2ecf20Sopenharmony_ci				DRM_ERROR("bad SET_APPEND_CNT (missing reloc)\n");
26468c2ecf20Sopenharmony_ci				return -EINVAL;
26478c2ecf20Sopenharmony_ci			}
26488c2ecf20Sopenharmony_ci			offset = radeon_get_ib_value(p, idx + 1);
26498c2ecf20Sopenharmony_ci			swap = offset & 0x3;
26508c2ecf20Sopenharmony_ci			offset &= ~0x3;
26518c2ecf20Sopenharmony_ci
26528c2ecf20Sopenharmony_ci			offset += ((u64)(radeon_get_ib_value(p, idx + 2) & 0xff)) << 32;
26538c2ecf20Sopenharmony_ci
26548c2ecf20Sopenharmony_ci			offset += reloc->gpu_offset;
26558c2ecf20Sopenharmony_ci			ib[idx+1] = (offset & 0xfffffffc) | swap;
26568c2ecf20Sopenharmony_ci			ib[idx+2] = upper_32_bits(offset) & 0xff;
26578c2ecf20Sopenharmony_ci		} else {
26588c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET_APPEND_CNT (unsupported operation)\n");
26598c2ecf20Sopenharmony_ci			return -EINVAL;
26608c2ecf20Sopenharmony_ci		}
26618c2ecf20Sopenharmony_ci		break;
26628c2ecf20Sopenharmony_ci	}
26638c2ecf20Sopenharmony_ci	case PACKET3_NOP:
26648c2ecf20Sopenharmony_ci		break;
26658c2ecf20Sopenharmony_ci	default:
26668c2ecf20Sopenharmony_ci		DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
26678c2ecf20Sopenharmony_ci		return -EINVAL;
26688c2ecf20Sopenharmony_ci	}
26698c2ecf20Sopenharmony_ci	return 0;
26708c2ecf20Sopenharmony_ci}
26718c2ecf20Sopenharmony_ci
26728c2ecf20Sopenharmony_ciint evergreen_cs_parse(struct radeon_cs_parser *p)
26738c2ecf20Sopenharmony_ci{
26748c2ecf20Sopenharmony_ci	struct radeon_cs_packet pkt;
26758c2ecf20Sopenharmony_ci	struct evergreen_cs_track *track;
26768c2ecf20Sopenharmony_ci	u32 tmp;
26778c2ecf20Sopenharmony_ci	int r;
26788c2ecf20Sopenharmony_ci
26798c2ecf20Sopenharmony_ci	if (p->track == NULL) {
26808c2ecf20Sopenharmony_ci		/* initialize tracker, we are in kms */
26818c2ecf20Sopenharmony_ci		track = kzalloc(sizeof(*track), GFP_KERNEL);
26828c2ecf20Sopenharmony_ci		if (track == NULL)
26838c2ecf20Sopenharmony_ci			return -ENOMEM;
26848c2ecf20Sopenharmony_ci		evergreen_cs_track_init(track);
26858c2ecf20Sopenharmony_ci		if (p->rdev->family >= CHIP_CAYMAN) {
26868c2ecf20Sopenharmony_ci			tmp = p->rdev->config.cayman.tile_config;
26878c2ecf20Sopenharmony_ci			track->reg_safe_bm = cayman_reg_safe_bm;
26888c2ecf20Sopenharmony_ci		} else {
26898c2ecf20Sopenharmony_ci			tmp = p->rdev->config.evergreen.tile_config;
26908c2ecf20Sopenharmony_ci			track->reg_safe_bm = evergreen_reg_safe_bm;
26918c2ecf20Sopenharmony_ci		}
26928c2ecf20Sopenharmony_ci		BUILD_BUG_ON(ARRAY_SIZE(cayman_reg_safe_bm) != REG_SAFE_BM_SIZE);
26938c2ecf20Sopenharmony_ci		BUILD_BUG_ON(ARRAY_SIZE(evergreen_reg_safe_bm) != REG_SAFE_BM_SIZE);
26948c2ecf20Sopenharmony_ci		switch (tmp & 0xf) {
26958c2ecf20Sopenharmony_ci		case 0:
26968c2ecf20Sopenharmony_ci			track->npipes = 1;
26978c2ecf20Sopenharmony_ci			break;
26988c2ecf20Sopenharmony_ci		case 1:
26998c2ecf20Sopenharmony_ci		default:
27008c2ecf20Sopenharmony_ci			track->npipes = 2;
27018c2ecf20Sopenharmony_ci			break;
27028c2ecf20Sopenharmony_ci		case 2:
27038c2ecf20Sopenharmony_ci			track->npipes = 4;
27048c2ecf20Sopenharmony_ci			break;
27058c2ecf20Sopenharmony_ci		case 3:
27068c2ecf20Sopenharmony_ci			track->npipes = 8;
27078c2ecf20Sopenharmony_ci			break;
27088c2ecf20Sopenharmony_ci		}
27098c2ecf20Sopenharmony_ci
27108c2ecf20Sopenharmony_ci		switch ((tmp & 0xf0) >> 4) {
27118c2ecf20Sopenharmony_ci		case 0:
27128c2ecf20Sopenharmony_ci			track->nbanks = 4;
27138c2ecf20Sopenharmony_ci			break;
27148c2ecf20Sopenharmony_ci		case 1:
27158c2ecf20Sopenharmony_ci		default:
27168c2ecf20Sopenharmony_ci			track->nbanks = 8;
27178c2ecf20Sopenharmony_ci			break;
27188c2ecf20Sopenharmony_ci		case 2:
27198c2ecf20Sopenharmony_ci			track->nbanks = 16;
27208c2ecf20Sopenharmony_ci			break;
27218c2ecf20Sopenharmony_ci		}
27228c2ecf20Sopenharmony_ci
27238c2ecf20Sopenharmony_ci		switch ((tmp & 0xf00) >> 8) {
27248c2ecf20Sopenharmony_ci		case 0:
27258c2ecf20Sopenharmony_ci			track->group_size = 256;
27268c2ecf20Sopenharmony_ci			break;
27278c2ecf20Sopenharmony_ci		case 1:
27288c2ecf20Sopenharmony_ci		default:
27298c2ecf20Sopenharmony_ci			track->group_size = 512;
27308c2ecf20Sopenharmony_ci			break;
27318c2ecf20Sopenharmony_ci		}
27328c2ecf20Sopenharmony_ci
27338c2ecf20Sopenharmony_ci		switch ((tmp & 0xf000) >> 12) {
27348c2ecf20Sopenharmony_ci		case 0:
27358c2ecf20Sopenharmony_ci			track->row_size = 1;
27368c2ecf20Sopenharmony_ci			break;
27378c2ecf20Sopenharmony_ci		case 1:
27388c2ecf20Sopenharmony_ci		default:
27398c2ecf20Sopenharmony_ci			track->row_size = 2;
27408c2ecf20Sopenharmony_ci			break;
27418c2ecf20Sopenharmony_ci		case 2:
27428c2ecf20Sopenharmony_ci			track->row_size = 4;
27438c2ecf20Sopenharmony_ci			break;
27448c2ecf20Sopenharmony_ci		}
27458c2ecf20Sopenharmony_ci
27468c2ecf20Sopenharmony_ci		p->track = track;
27478c2ecf20Sopenharmony_ci	}
27488c2ecf20Sopenharmony_ci	do {
27498c2ecf20Sopenharmony_ci		r = radeon_cs_packet_parse(p, &pkt, p->idx);
27508c2ecf20Sopenharmony_ci		if (r) {
27518c2ecf20Sopenharmony_ci			kfree(p->track);
27528c2ecf20Sopenharmony_ci			p->track = NULL;
27538c2ecf20Sopenharmony_ci			return r;
27548c2ecf20Sopenharmony_ci		}
27558c2ecf20Sopenharmony_ci		p->idx += pkt.count + 2;
27568c2ecf20Sopenharmony_ci		switch (pkt.type) {
27578c2ecf20Sopenharmony_ci		case RADEON_PACKET_TYPE0:
27588c2ecf20Sopenharmony_ci			r = evergreen_cs_parse_packet0(p, &pkt);
27598c2ecf20Sopenharmony_ci			break;
27608c2ecf20Sopenharmony_ci		case RADEON_PACKET_TYPE2:
27618c2ecf20Sopenharmony_ci			break;
27628c2ecf20Sopenharmony_ci		case RADEON_PACKET_TYPE3:
27638c2ecf20Sopenharmony_ci			r = evergreen_packet3_check(p, &pkt);
27648c2ecf20Sopenharmony_ci			break;
27658c2ecf20Sopenharmony_ci		default:
27668c2ecf20Sopenharmony_ci			DRM_ERROR("Unknown packet type %d !\n", pkt.type);
27678c2ecf20Sopenharmony_ci			kfree(p->track);
27688c2ecf20Sopenharmony_ci			p->track = NULL;
27698c2ecf20Sopenharmony_ci			return -EINVAL;
27708c2ecf20Sopenharmony_ci		}
27718c2ecf20Sopenharmony_ci		if (r) {
27728c2ecf20Sopenharmony_ci			kfree(p->track);
27738c2ecf20Sopenharmony_ci			p->track = NULL;
27748c2ecf20Sopenharmony_ci			return r;
27758c2ecf20Sopenharmony_ci		}
27768c2ecf20Sopenharmony_ci	} while (p->idx < p->chunk_ib->length_dw);
27778c2ecf20Sopenharmony_ci#if 0
27788c2ecf20Sopenharmony_ci	for (r = 0; r < p->ib.length_dw; r++) {
27798c2ecf20Sopenharmony_ci		pr_info("%05d  0x%08X\n", r, p->ib.ptr[r]);
27808c2ecf20Sopenharmony_ci		mdelay(1);
27818c2ecf20Sopenharmony_ci	}
27828c2ecf20Sopenharmony_ci#endif
27838c2ecf20Sopenharmony_ci	kfree(p->track);
27848c2ecf20Sopenharmony_ci	p->track = NULL;
27858c2ecf20Sopenharmony_ci	return 0;
27868c2ecf20Sopenharmony_ci}
27878c2ecf20Sopenharmony_ci
27888c2ecf20Sopenharmony_ci/**
27898c2ecf20Sopenharmony_ci * evergreen_dma_cs_parse() - parse the DMA IB
27908c2ecf20Sopenharmony_ci * @p:		parser structure holding parsing context.
27918c2ecf20Sopenharmony_ci *
27928c2ecf20Sopenharmony_ci * Parses the DMA IB from the CS ioctl and updates
27938c2ecf20Sopenharmony_ci * the GPU addresses based on the reloc information and
27948c2ecf20Sopenharmony_ci * checks for errors. (Evergreen-Cayman)
27958c2ecf20Sopenharmony_ci * Returns 0 for success and an error on failure.
27968c2ecf20Sopenharmony_ci **/
27978c2ecf20Sopenharmony_ciint evergreen_dma_cs_parse(struct radeon_cs_parser *p)
27988c2ecf20Sopenharmony_ci{
27998c2ecf20Sopenharmony_ci	struct radeon_cs_chunk *ib_chunk = p->chunk_ib;
28008c2ecf20Sopenharmony_ci	struct radeon_bo_list *src_reloc, *dst_reloc, *dst2_reloc;
28018c2ecf20Sopenharmony_ci	u32 header, cmd, count, sub_cmd;
28028c2ecf20Sopenharmony_ci	uint32_t *ib = p->ib.ptr;
28038c2ecf20Sopenharmony_ci	u32 idx;
28048c2ecf20Sopenharmony_ci	u64 src_offset, dst_offset, dst2_offset;
28058c2ecf20Sopenharmony_ci	int r;
28068c2ecf20Sopenharmony_ci
28078c2ecf20Sopenharmony_ci	do {
28088c2ecf20Sopenharmony_ci		if (p->idx >= ib_chunk->length_dw) {
28098c2ecf20Sopenharmony_ci			DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
28108c2ecf20Sopenharmony_ci				  p->idx, ib_chunk->length_dw);
28118c2ecf20Sopenharmony_ci			return -EINVAL;
28128c2ecf20Sopenharmony_ci		}
28138c2ecf20Sopenharmony_ci		idx = p->idx;
28148c2ecf20Sopenharmony_ci		header = radeon_get_ib_value(p, idx);
28158c2ecf20Sopenharmony_ci		cmd = GET_DMA_CMD(header);
28168c2ecf20Sopenharmony_ci		count = GET_DMA_COUNT(header);
28178c2ecf20Sopenharmony_ci		sub_cmd = GET_DMA_SUB_CMD(header);
28188c2ecf20Sopenharmony_ci
28198c2ecf20Sopenharmony_ci		switch (cmd) {
28208c2ecf20Sopenharmony_ci		case DMA_PACKET_WRITE:
28218c2ecf20Sopenharmony_ci			r = r600_dma_cs_next_reloc(p, &dst_reloc);
28228c2ecf20Sopenharmony_ci			if (r) {
28238c2ecf20Sopenharmony_ci				DRM_ERROR("bad DMA_PACKET_WRITE\n");
28248c2ecf20Sopenharmony_ci				return -EINVAL;
28258c2ecf20Sopenharmony_ci			}
28268c2ecf20Sopenharmony_ci			switch (sub_cmd) {
28278c2ecf20Sopenharmony_ci			/* tiled */
28288c2ecf20Sopenharmony_ci			case 8:
28298c2ecf20Sopenharmony_ci				dst_offset = radeon_get_ib_value(p, idx+1);
28308c2ecf20Sopenharmony_ci				dst_offset <<= 8;
28318c2ecf20Sopenharmony_ci
28328c2ecf20Sopenharmony_ci				ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8);
28338c2ecf20Sopenharmony_ci				p->idx += count + 7;
28348c2ecf20Sopenharmony_ci				break;
28358c2ecf20Sopenharmony_ci			/* linear */
28368c2ecf20Sopenharmony_ci			case 0:
28378c2ecf20Sopenharmony_ci				dst_offset = radeon_get_ib_value(p, idx+1);
28388c2ecf20Sopenharmony_ci				dst_offset |= ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
28398c2ecf20Sopenharmony_ci
28408c2ecf20Sopenharmony_ci				ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
28418c2ecf20Sopenharmony_ci				ib[idx+2] += upper_32_bits(dst_reloc->gpu_offset) & 0xff;
28428c2ecf20Sopenharmony_ci				p->idx += count + 3;
28438c2ecf20Sopenharmony_ci				break;
28448c2ecf20Sopenharmony_ci			default:
28458c2ecf20Sopenharmony_ci				DRM_ERROR("bad DMA_PACKET_WRITE [%6d] 0x%08x sub cmd is not 0 or 8\n", idx, header);
28468c2ecf20Sopenharmony_ci				return -EINVAL;
28478c2ecf20Sopenharmony_ci			}
28488c2ecf20Sopenharmony_ci			if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
28498c2ecf20Sopenharmony_ci				dev_warn(p->dev, "DMA write buffer too small (%llu %lu)\n",
28508c2ecf20Sopenharmony_ci					 dst_offset, radeon_bo_size(dst_reloc->robj));
28518c2ecf20Sopenharmony_ci				return -EINVAL;
28528c2ecf20Sopenharmony_ci			}
28538c2ecf20Sopenharmony_ci			break;
28548c2ecf20Sopenharmony_ci		case DMA_PACKET_COPY:
28558c2ecf20Sopenharmony_ci			r = r600_dma_cs_next_reloc(p, &src_reloc);
28568c2ecf20Sopenharmony_ci			if (r) {
28578c2ecf20Sopenharmony_ci				DRM_ERROR("bad DMA_PACKET_COPY\n");
28588c2ecf20Sopenharmony_ci				return -EINVAL;
28598c2ecf20Sopenharmony_ci			}
28608c2ecf20Sopenharmony_ci			r = r600_dma_cs_next_reloc(p, &dst_reloc);
28618c2ecf20Sopenharmony_ci			if (r) {
28628c2ecf20Sopenharmony_ci				DRM_ERROR("bad DMA_PACKET_COPY\n");
28638c2ecf20Sopenharmony_ci				return -EINVAL;
28648c2ecf20Sopenharmony_ci			}
28658c2ecf20Sopenharmony_ci			switch (sub_cmd) {
28668c2ecf20Sopenharmony_ci			/* Copy L2L, DW aligned */
28678c2ecf20Sopenharmony_ci			case 0x00:
28688c2ecf20Sopenharmony_ci				/* L2L, dw */
28698c2ecf20Sopenharmony_ci				src_offset = radeon_get_ib_value(p, idx+2);
28708c2ecf20Sopenharmony_ci				src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
28718c2ecf20Sopenharmony_ci				dst_offset = radeon_get_ib_value(p, idx+1);
28728c2ecf20Sopenharmony_ci				dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
28738c2ecf20Sopenharmony_ci				if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
28748c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2L, dw src buffer too small (%llu %lu)\n",
28758c2ecf20Sopenharmony_ci							src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
28768c2ecf20Sopenharmony_ci					return -EINVAL;
28778c2ecf20Sopenharmony_ci				}
28788c2ecf20Sopenharmony_ci				if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
28798c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2L, dw dst buffer too small (%llu %lu)\n",
28808c2ecf20Sopenharmony_ci							dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
28818c2ecf20Sopenharmony_ci					return -EINVAL;
28828c2ecf20Sopenharmony_ci				}
28838c2ecf20Sopenharmony_ci				ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
28848c2ecf20Sopenharmony_ci				ib[idx+2] += (u32)(src_reloc->gpu_offset & 0xfffffffc);
28858c2ecf20Sopenharmony_ci				ib[idx+3] += upper_32_bits(dst_reloc->gpu_offset) & 0xff;
28868c2ecf20Sopenharmony_ci				ib[idx+4] += upper_32_bits(src_reloc->gpu_offset) & 0xff;
28878c2ecf20Sopenharmony_ci				p->idx += 5;
28888c2ecf20Sopenharmony_ci				break;
28898c2ecf20Sopenharmony_ci			/* Copy L2T/T2L */
28908c2ecf20Sopenharmony_ci			case 0x08:
28918c2ecf20Sopenharmony_ci				/* detile bit */
28928c2ecf20Sopenharmony_ci				if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) {
28938c2ecf20Sopenharmony_ci					/* tiled src, linear dst */
28948c2ecf20Sopenharmony_ci					src_offset = radeon_get_ib_value(p, idx+1);
28958c2ecf20Sopenharmony_ci					src_offset <<= 8;
28968c2ecf20Sopenharmony_ci					ib[idx+1] += (u32)(src_reloc->gpu_offset >> 8);
28978c2ecf20Sopenharmony_ci
28988c2ecf20Sopenharmony_ci					dst_offset = radeon_get_ib_value(p, idx + 7);
28998c2ecf20Sopenharmony_ci					dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
29008c2ecf20Sopenharmony_ci					ib[idx+7] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
29018c2ecf20Sopenharmony_ci					ib[idx+8] += upper_32_bits(dst_reloc->gpu_offset) & 0xff;
29028c2ecf20Sopenharmony_ci				} else {
29038c2ecf20Sopenharmony_ci					/* linear src, tiled dst */
29048c2ecf20Sopenharmony_ci					src_offset = radeon_get_ib_value(p, idx+7);
29058c2ecf20Sopenharmony_ci					src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
29068c2ecf20Sopenharmony_ci					ib[idx+7] += (u32)(src_reloc->gpu_offset & 0xfffffffc);
29078c2ecf20Sopenharmony_ci					ib[idx+8] += upper_32_bits(src_reloc->gpu_offset) & 0xff;
29088c2ecf20Sopenharmony_ci
29098c2ecf20Sopenharmony_ci					dst_offset = radeon_get_ib_value(p, idx+1);
29108c2ecf20Sopenharmony_ci					dst_offset <<= 8;
29118c2ecf20Sopenharmony_ci					ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8);
29128c2ecf20Sopenharmony_ci				}
29138c2ecf20Sopenharmony_ci				if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
29148c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2T, src buffer too small (%llu %lu)\n",
29158c2ecf20Sopenharmony_ci							src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
29168c2ecf20Sopenharmony_ci					return -EINVAL;
29178c2ecf20Sopenharmony_ci				}
29188c2ecf20Sopenharmony_ci				if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
29198c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2T, dst buffer too small (%llu %lu)\n",
29208c2ecf20Sopenharmony_ci							dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
29218c2ecf20Sopenharmony_ci					return -EINVAL;
29228c2ecf20Sopenharmony_ci				}
29238c2ecf20Sopenharmony_ci				p->idx += 9;
29248c2ecf20Sopenharmony_ci				break;
29258c2ecf20Sopenharmony_ci			/* Copy L2L, byte aligned */
29268c2ecf20Sopenharmony_ci			case 0x40:
29278c2ecf20Sopenharmony_ci				/* L2L, byte */
29288c2ecf20Sopenharmony_ci				src_offset = radeon_get_ib_value(p, idx+2);
29298c2ecf20Sopenharmony_ci				src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
29308c2ecf20Sopenharmony_ci				dst_offset = radeon_get_ib_value(p, idx+1);
29318c2ecf20Sopenharmony_ci				dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
29328c2ecf20Sopenharmony_ci				if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) {
29338c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2L, byte src buffer too small (%llu %lu)\n",
29348c2ecf20Sopenharmony_ci							src_offset + count, radeon_bo_size(src_reloc->robj));
29358c2ecf20Sopenharmony_ci					return -EINVAL;
29368c2ecf20Sopenharmony_ci				}
29378c2ecf20Sopenharmony_ci				if ((dst_offset + count) > radeon_bo_size(dst_reloc->robj)) {
29388c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2L, byte dst buffer too small (%llu %lu)\n",
29398c2ecf20Sopenharmony_ci							dst_offset + count, radeon_bo_size(dst_reloc->robj));
29408c2ecf20Sopenharmony_ci					return -EINVAL;
29418c2ecf20Sopenharmony_ci				}
29428c2ecf20Sopenharmony_ci				ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xffffffff);
29438c2ecf20Sopenharmony_ci				ib[idx+2] += (u32)(src_reloc->gpu_offset & 0xffffffff);
29448c2ecf20Sopenharmony_ci				ib[idx+3] += upper_32_bits(dst_reloc->gpu_offset) & 0xff;
29458c2ecf20Sopenharmony_ci				ib[idx+4] += upper_32_bits(src_reloc->gpu_offset) & 0xff;
29468c2ecf20Sopenharmony_ci				p->idx += 5;
29478c2ecf20Sopenharmony_ci				break;
29488c2ecf20Sopenharmony_ci			/* Copy L2L, partial */
29498c2ecf20Sopenharmony_ci			case 0x41:
29508c2ecf20Sopenharmony_ci				/* L2L, partial */
29518c2ecf20Sopenharmony_ci				if (p->family < CHIP_CAYMAN) {
29528c2ecf20Sopenharmony_ci					DRM_ERROR("L2L Partial is cayman only !\n");
29538c2ecf20Sopenharmony_ci					return -EINVAL;
29548c2ecf20Sopenharmony_ci				}
29558c2ecf20Sopenharmony_ci				ib[idx+1] += (u32)(src_reloc->gpu_offset & 0xffffffff);
29568c2ecf20Sopenharmony_ci				ib[idx+2] += upper_32_bits(src_reloc->gpu_offset) & 0xff;
29578c2ecf20Sopenharmony_ci				ib[idx+4] += (u32)(dst_reloc->gpu_offset & 0xffffffff);
29588c2ecf20Sopenharmony_ci				ib[idx+5] += upper_32_bits(dst_reloc->gpu_offset) & 0xff;
29598c2ecf20Sopenharmony_ci
29608c2ecf20Sopenharmony_ci				p->idx += 9;
29618c2ecf20Sopenharmony_ci				break;
29628c2ecf20Sopenharmony_ci			/* Copy L2L, DW aligned, broadcast */
29638c2ecf20Sopenharmony_ci			case 0x44:
29648c2ecf20Sopenharmony_ci				/* L2L, dw, broadcast */
29658c2ecf20Sopenharmony_ci				r = r600_dma_cs_next_reloc(p, &dst2_reloc);
29668c2ecf20Sopenharmony_ci				if (r) {
29678c2ecf20Sopenharmony_ci					DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n");
29688c2ecf20Sopenharmony_ci					return -EINVAL;
29698c2ecf20Sopenharmony_ci				}
29708c2ecf20Sopenharmony_ci				dst_offset = radeon_get_ib_value(p, idx+1);
29718c2ecf20Sopenharmony_ci				dst_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
29728c2ecf20Sopenharmony_ci				dst2_offset = radeon_get_ib_value(p, idx+2);
29738c2ecf20Sopenharmony_ci				dst2_offset |= ((u64)(radeon_get_ib_value(p, idx+5) & 0xff)) << 32;
29748c2ecf20Sopenharmony_ci				src_offset = radeon_get_ib_value(p, idx+3);
29758c2ecf20Sopenharmony_ci				src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32;
29768c2ecf20Sopenharmony_ci				if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
29778c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%llu %lu)\n",
29788c2ecf20Sopenharmony_ci							src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
29798c2ecf20Sopenharmony_ci					return -EINVAL;
29808c2ecf20Sopenharmony_ci				}
29818c2ecf20Sopenharmony_ci				if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
29828c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2L, dw, broadcast dst buffer too small (%llu %lu)\n",
29838c2ecf20Sopenharmony_ci							dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
29848c2ecf20Sopenharmony_ci					return -EINVAL;
29858c2ecf20Sopenharmony_ci				}
29868c2ecf20Sopenharmony_ci				if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
29878c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2L, dw, broadcast dst2 buffer too small (%llu %lu)\n",
29888c2ecf20Sopenharmony_ci							dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
29898c2ecf20Sopenharmony_ci					return -EINVAL;
29908c2ecf20Sopenharmony_ci				}
29918c2ecf20Sopenharmony_ci				ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
29928c2ecf20Sopenharmony_ci				ib[idx+2] += (u32)(dst2_reloc->gpu_offset & 0xfffffffc);
29938c2ecf20Sopenharmony_ci				ib[idx+3] += (u32)(src_reloc->gpu_offset & 0xfffffffc);
29948c2ecf20Sopenharmony_ci				ib[idx+4] += upper_32_bits(dst_reloc->gpu_offset) & 0xff;
29958c2ecf20Sopenharmony_ci				ib[idx+5] += upper_32_bits(dst2_reloc->gpu_offset) & 0xff;
29968c2ecf20Sopenharmony_ci				ib[idx+6] += upper_32_bits(src_reloc->gpu_offset) & 0xff;
29978c2ecf20Sopenharmony_ci				p->idx += 7;
29988c2ecf20Sopenharmony_ci				break;
29998c2ecf20Sopenharmony_ci			/* Copy L2T Frame to Field */
30008c2ecf20Sopenharmony_ci			case 0x48:
30018c2ecf20Sopenharmony_ci				if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) {
30028c2ecf20Sopenharmony_ci					DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
30038c2ecf20Sopenharmony_ci					return -EINVAL;
30048c2ecf20Sopenharmony_ci				}
30058c2ecf20Sopenharmony_ci				r = r600_dma_cs_next_reloc(p, &dst2_reloc);
30068c2ecf20Sopenharmony_ci				if (r) {
30078c2ecf20Sopenharmony_ci					DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
30088c2ecf20Sopenharmony_ci					return -EINVAL;
30098c2ecf20Sopenharmony_ci				}
30108c2ecf20Sopenharmony_ci				dst_offset = radeon_get_ib_value(p, idx+1);
30118c2ecf20Sopenharmony_ci				dst_offset <<= 8;
30128c2ecf20Sopenharmony_ci				dst2_offset = radeon_get_ib_value(p, idx+2);
30138c2ecf20Sopenharmony_ci				dst2_offset <<= 8;
30148c2ecf20Sopenharmony_ci				src_offset = radeon_get_ib_value(p, idx+8);
30158c2ecf20Sopenharmony_ci				src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32;
30168c2ecf20Sopenharmony_ci				if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
30178c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%llu %lu)\n",
30188c2ecf20Sopenharmony_ci							src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
30198c2ecf20Sopenharmony_ci					return -EINVAL;
30208c2ecf20Sopenharmony_ci				}
30218c2ecf20Sopenharmony_ci				if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
30228c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n",
30238c2ecf20Sopenharmony_ci							dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
30248c2ecf20Sopenharmony_ci					return -EINVAL;
30258c2ecf20Sopenharmony_ci				}
30268c2ecf20Sopenharmony_ci				if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
30278c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n",
30288c2ecf20Sopenharmony_ci							dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
30298c2ecf20Sopenharmony_ci					return -EINVAL;
30308c2ecf20Sopenharmony_ci				}
30318c2ecf20Sopenharmony_ci				ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8);
30328c2ecf20Sopenharmony_ci				ib[idx+2] += (u32)(dst2_reloc->gpu_offset >> 8);
30338c2ecf20Sopenharmony_ci				ib[idx+8] += (u32)(src_reloc->gpu_offset & 0xfffffffc);
30348c2ecf20Sopenharmony_ci				ib[idx+9] += upper_32_bits(src_reloc->gpu_offset) & 0xff;
30358c2ecf20Sopenharmony_ci				p->idx += 10;
30368c2ecf20Sopenharmony_ci				break;
30378c2ecf20Sopenharmony_ci			/* Copy L2T/T2L, partial */
30388c2ecf20Sopenharmony_ci			case 0x49:
30398c2ecf20Sopenharmony_ci				/* L2T, T2L partial */
30408c2ecf20Sopenharmony_ci				if (p->family < CHIP_CAYMAN) {
30418c2ecf20Sopenharmony_ci					DRM_ERROR("L2T, T2L Partial is cayman only !\n");
30428c2ecf20Sopenharmony_ci					return -EINVAL;
30438c2ecf20Sopenharmony_ci				}
30448c2ecf20Sopenharmony_ci				/* detile bit */
30458c2ecf20Sopenharmony_ci				if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) {
30468c2ecf20Sopenharmony_ci					/* tiled src, linear dst */
30478c2ecf20Sopenharmony_ci					ib[idx+1] += (u32)(src_reloc->gpu_offset >> 8);
30488c2ecf20Sopenharmony_ci
30498c2ecf20Sopenharmony_ci					ib[idx+7] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
30508c2ecf20Sopenharmony_ci					ib[idx+8] += upper_32_bits(dst_reloc->gpu_offset) & 0xff;
30518c2ecf20Sopenharmony_ci				} else {
30528c2ecf20Sopenharmony_ci					/* linear src, tiled dst */
30538c2ecf20Sopenharmony_ci					ib[idx+7] += (u32)(src_reloc->gpu_offset & 0xfffffffc);
30548c2ecf20Sopenharmony_ci					ib[idx+8] += upper_32_bits(src_reloc->gpu_offset) & 0xff;
30558c2ecf20Sopenharmony_ci
30568c2ecf20Sopenharmony_ci					ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8);
30578c2ecf20Sopenharmony_ci				}
30588c2ecf20Sopenharmony_ci				p->idx += 12;
30598c2ecf20Sopenharmony_ci				break;
30608c2ecf20Sopenharmony_ci			/* Copy L2T broadcast */
30618c2ecf20Sopenharmony_ci			case 0x4b:
30628c2ecf20Sopenharmony_ci				/* L2T, broadcast */
30638c2ecf20Sopenharmony_ci				if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) {
30648c2ecf20Sopenharmony_ci					DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
30658c2ecf20Sopenharmony_ci					return -EINVAL;
30668c2ecf20Sopenharmony_ci				}
30678c2ecf20Sopenharmony_ci				r = r600_dma_cs_next_reloc(p, &dst2_reloc);
30688c2ecf20Sopenharmony_ci				if (r) {
30698c2ecf20Sopenharmony_ci					DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
30708c2ecf20Sopenharmony_ci					return -EINVAL;
30718c2ecf20Sopenharmony_ci				}
30728c2ecf20Sopenharmony_ci				dst_offset = radeon_get_ib_value(p, idx+1);
30738c2ecf20Sopenharmony_ci				dst_offset <<= 8;
30748c2ecf20Sopenharmony_ci				dst2_offset = radeon_get_ib_value(p, idx+2);
30758c2ecf20Sopenharmony_ci				dst2_offset <<= 8;
30768c2ecf20Sopenharmony_ci				src_offset = radeon_get_ib_value(p, idx+8);
30778c2ecf20Sopenharmony_ci				src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32;
30788c2ecf20Sopenharmony_ci				if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
30798c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
30808c2ecf20Sopenharmony_ci							src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
30818c2ecf20Sopenharmony_ci					return -EINVAL;
30828c2ecf20Sopenharmony_ci				}
30838c2ecf20Sopenharmony_ci				if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
30848c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
30858c2ecf20Sopenharmony_ci							dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
30868c2ecf20Sopenharmony_ci					return -EINVAL;
30878c2ecf20Sopenharmony_ci				}
30888c2ecf20Sopenharmony_ci				if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
30898c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n",
30908c2ecf20Sopenharmony_ci							dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
30918c2ecf20Sopenharmony_ci					return -EINVAL;
30928c2ecf20Sopenharmony_ci				}
30938c2ecf20Sopenharmony_ci				ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8);
30948c2ecf20Sopenharmony_ci				ib[idx+2] += (u32)(dst2_reloc->gpu_offset >> 8);
30958c2ecf20Sopenharmony_ci				ib[idx+8] += (u32)(src_reloc->gpu_offset & 0xfffffffc);
30968c2ecf20Sopenharmony_ci				ib[idx+9] += upper_32_bits(src_reloc->gpu_offset) & 0xff;
30978c2ecf20Sopenharmony_ci				p->idx += 10;
30988c2ecf20Sopenharmony_ci				break;
30998c2ecf20Sopenharmony_ci			/* Copy L2T/T2L (tile units) */
31008c2ecf20Sopenharmony_ci			case 0x4c:
31018c2ecf20Sopenharmony_ci				/* L2T, T2L */
31028c2ecf20Sopenharmony_ci				/* detile bit */
31038c2ecf20Sopenharmony_ci				if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) {
31048c2ecf20Sopenharmony_ci					/* tiled src, linear dst */
31058c2ecf20Sopenharmony_ci					src_offset = radeon_get_ib_value(p, idx+1);
31068c2ecf20Sopenharmony_ci					src_offset <<= 8;
31078c2ecf20Sopenharmony_ci					ib[idx+1] += (u32)(src_reloc->gpu_offset >> 8);
31088c2ecf20Sopenharmony_ci
31098c2ecf20Sopenharmony_ci					dst_offset = radeon_get_ib_value(p, idx+7);
31108c2ecf20Sopenharmony_ci					dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
31118c2ecf20Sopenharmony_ci					ib[idx+7] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
31128c2ecf20Sopenharmony_ci					ib[idx+8] += upper_32_bits(dst_reloc->gpu_offset) & 0xff;
31138c2ecf20Sopenharmony_ci				} else {
31148c2ecf20Sopenharmony_ci					/* linear src, tiled dst */
31158c2ecf20Sopenharmony_ci					src_offset = radeon_get_ib_value(p, idx+7);
31168c2ecf20Sopenharmony_ci					src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
31178c2ecf20Sopenharmony_ci					ib[idx+7] += (u32)(src_reloc->gpu_offset & 0xfffffffc);
31188c2ecf20Sopenharmony_ci					ib[idx+8] += upper_32_bits(src_reloc->gpu_offset) & 0xff;
31198c2ecf20Sopenharmony_ci
31208c2ecf20Sopenharmony_ci					dst_offset = radeon_get_ib_value(p, idx+1);
31218c2ecf20Sopenharmony_ci					dst_offset <<= 8;
31228c2ecf20Sopenharmony_ci					ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8);
31238c2ecf20Sopenharmony_ci				}
31248c2ecf20Sopenharmony_ci				if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
31258c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2T, T2L src buffer too small (%llu %lu)\n",
31268c2ecf20Sopenharmony_ci							src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
31278c2ecf20Sopenharmony_ci					return -EINVAL;
31288c2ecf20Sopenharmony_ci				}
31298c2ecf20Sopenharmony_ci				if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
31308c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2T, T2L dst buffer too small (%llu %lu)\n",
31318c2ecf20Sopenharmony_ci							dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
31328c2ecf20Sopenharmony_ci					return -EINVAL;
31338c2ecf20Sopenharmony_ci				}
31348c2ecf20Sopenharmony_ci				p->idx += 9;
31358c2ecf20Sopenharmony_ci				break;
31368c2ecf20Sopenharmony_ci			/* Copy T2T, partial (tile units) */
31378c2ecf20Sopenharmony_ci			case 0x4d:
31388c2ecf20Sopenharmony_ci				/* T2T partial */
31398c2ecf20Sopenharmony_ci				if (p->family < CHIP_CAYMAN) {
31408c2ecf20Sopenharmony_ci					DRM_ERROR("L2T, T2L Partial is cayman only !\n");
31418c2ecf20Sopenharmony_ci					return -EINVAL;
31428c2ecf20Sopenharmony_ci				}
31438c2ecf20Sopenharmony_ci				ib[idx+1] += (u32)(src_reloc->gpu_offset >> 8);
31448c2ecf20Sopenharmony_ci				ib[idx+4] += (u32)(dst_reloc->gpu_offset >> 8);
31458c2ecf20Sopenharmony_ci				p->idx += 13;
31468c2ecf20Sopenharmony_ci				break;
31478c2ecf20Sopenharmony_ci			/* Copy L2T broadcast (tile units) */
31488c2ecf20Sopenharmony_ci			case 0x4f:
31498c2ecf20Sopenharmony_ci				/* L2T, broadcast */
31508c2ecf20Sopenharmony_ci				if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) {
31518c2ecf20Sopenharmony_ci					DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
31528c2ecf20Sopenharmony_ci					return -EINVAL;
31538c2ecf20Sopenharmony_ci				}
31548c2ecf20Sopenharmony_ci				r = r600_dma_cs_next_reloc(p, &dst2_reloc);
31558c2ecf20Sopenharmony_ci				if (r) {
31568c2ecf20Sopenharmony_ci					DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
31578c2ecf20Sopenharmony_ci					return -EINVAL;
31588c2ecf20Sopenharmony_ci				}
31598c2ecf20Sopenharmony_ci				dst_offset = radeon_get_ib_value(p, idx+1);
31608c2ecf20Sopenharmony_ci				dst_offset <<= 8;
31618c2ecf20Sopenharmony_ci				dst2_offset = radeon_get_ib_value(p, idx+2);
31628c2ecf20Sopenharmony_ci				dst2_offset <<= 8;
31638c2ecf20Sopenharmony_ci				src_offset = radeon_get_ib_value(p, idx+8);
31648c2ecf20Sopenharmony_ci				src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32;
31658c2ecf20Sopenharmony_ci				if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
31668c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
31678c2ecf20Sopenharmony_ci							src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
31688c2ecf20Sopenharmony_ci					return -EINVAL;
31698c2ecf20Sopenharmony_ci				}
31708c2ecf20Sopenharmony_ci				if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
31718c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
31728c2ecf20Sopenharmony_ci							dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
31738c2ecf20Sopenharmony_ci					return -EINVAL;
31748c2ecf20Sopenharmony_ci				}
31758c2ecf20Sopenharmony_ci				if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
31768c2ecf20Sopenharmony_ci					dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n",
31778c2ecf20Sopenharmony_ci							dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
31788c2ecf20Sopenharmony_ci					return -EINVAL;
31798c2ecf20Sopenharmony_ci				}
31808c2ecf20Sopenharmony_ci				ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8);
31818c2ecf20Sopenharmony_ci				ib[idx+2] += (u32)(dst2_reloc->gpu_offset >> 8);
31828c2ecf20Sopenharmony_ci				ib[idx+8] += (u32)(src_reloc->gpu_offset & 0xfffffffc);
31838c2ecf20Sopenharmony_ci				ib[idx+9] += upper_32_bits(src_reloc->gpu_offset) & 0xff;
31848c2ecf20Sopenharmony_ci				p->idx += 10;
31858c2ecf20Sopenharmony_ci				break;
31868c2ecf20Sopenharmony_ci			default:
31878c2ecf20Sopenharmony_ci				DRM_ERROR("bad DMA_PACKET_COPY [%6d] 0x%08x invalid sub cmd\n", idx, header);
31888c2ecf20Sopenharmony_ci				return -EINVAL;
31898c2ecf20Sopenharmony_ci			}
31908c2ecf20Sopenharmony_ci			break;
31918c2ecf20Sopenharmony_ci		case DMA_PACKET_CONSTANT_FILL:
31928c2ecf20Sopenharmony_ci			r = r600_dma_cs_next_reloc(p, &dst_reloc);
31938c2ecf20Sopenharmony_ci			if (r) {
31948c2ecf20Sopenharmony_ci				DRM_ERROR("bad DMA_PACKET_CONSTANT_FILL\n");
31958c2ecf20Sopenharmony_ci				return -EINVAL;
31968c2ecf20Sopenharmony_ci			}
31978c2ecf20Sopenharmony_ci			dst_offset = radeon_get_ib_value(p, idx+1);
31988c2ecf20Sopenharmony_ci			dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0x00ff0000)) << 16;
31998c2ecf20Sopenharmony_ci			if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
32008c2ecf20Sopenharmony_ci				dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n",
32018c2ecf20Sopenharmony_ci					 dst_offset, radeon_bo_size(dst_reloc->robj));
32028c2ecf20Sopenharmony_ci				return -EINVAL;
32038c2ecf20Sopenharmony_ci			}
32048c2ecf20Sopenharmony_ci			ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
32058c2ecf20Sopenharmony_ci			ib[idx+3] += (upper_32_bits(dst_reloc->gpu_offset) << 16) & 0x00ff0000;
32068c2ecf20Sopenharmony_ci			p->idx += 4;
32078c2ecf20Sopenharmony_ci			break;
32088c2ecf20Sopenharmony_ci		case DMA_PACKET_NOP:
32098c2ecf20Sopenharmony_ci			p->idx += 1;
32108c2ecf20Sopenharmony_ci			break;
32118c2ecf20Sopenharmony_ci		default:
32128c2ecf20Sopenharmony_ci			DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx);
32138c2ecf20Sopenharmony_ci			return -EINVAL;
32148c2ecf20Sopenharmony_ci		}
32158c2ecf20Sopenharmony_ci	} while (p->idx < p->chunk_ib->length_dw);
32168c2ecf20Sopenharmony_ci#if 0
32178c2ecf20Sopenharmony_ci	for (r = 0; r < p->ib->length_dw; r++) {
32188c2ecf20Sopenharmony_ci		pr_info("%05d  0x%08X\n", r, p->ib.ptr[r]);
32198c2ecf20Sopenharmony_ci		mdelay(1);
32208c2ecf20Sopenharmony_ci	}
32218c2ecf20Sopenharmony_ci#endif
32228c2ecf20Sopenharmony_ci	return 0;
32238c2ecf20Sopenharmony_ci}
32248c2ecf20Sopenharmony_ci
32258c2ecf20Sopenharmony_ci/* vm parser */
32268c2ecf20Sopenharmony_cistatic bool evergreen_vm_reg_valid(u32 reg)
32278c2ecf20Sopenharmony_ci{
32288c2ecf20Sopenharmony_ci	/* context regs are fine */
32298c2ecf20Sopenharmony_ci	if (reg >= 0x28000)
32308c2ecf20Sopenharmony_ci		return true;
32318c2ecf20Sopenharmony_ci
32328c2ecf20Sopenharmony_ci	/* check config regs */
32338c2ecf20Sopenharmony_ci	switch (reg) {
32348c2ecf20Sopenharmony_ci	case WAIT_UNTIL:
32358c2ecf20Sopenharmony_ci	case GRBM_GFX_INDEX:
32368c2ecf20Sopenharmony_ci	case CP_STRMOUT_CNTL:
32378c2ecf20Sopenharmony_ci	case CP_COHER_CNTL:
32388c2ecf20Sopenharmony_ci	case CP_COHER_SIZE:
32398c2ecf20Sopenharmony_ci	case VGT_VTX_VECT_EJECT_REG:
32408c2ecf20Sopenharmony_ci	case VGT_CACHE_INVALIDATION:
32418c2ecf20Sopenharmony_ci	case VGT_GS_VERTEX_REUSE:
32428c2ecf20Sopenharmony_ci	case VGT_PRIMITIVE_TYPE:
32438c2ecf20Sopenharmony_ci	case VGT_INDEX_TYPE:
32448c2ecf20Sopenharmony_ci	case VGT_NUM_INDICES:
32458c2ecf20Sopenharmony_ci	case VGT_NUM_INSTANCES:
32468c2ecf20Sopenharmony_ci	case VGT_COMPUTE_DIM_X:
32478c2ecf20Sopenharmony_ci	case VGT_COMPUTE_DIM_Y:
32488c2ecf20Sopenharmony_ci	case VGT_COMPUTE_DIM_Z:
32498c2ecf20Sopenharmony_ci	case VGT_COMPUTE_START_X:
32508c2ecf20Sopenharmony_ci	case VGT_COMPUTE_START_Y:
32518c2ecf20Sopenharmony_ci	case VGT_COMPUTE_START_Z:
32528c2ecf20Sopenharmony_ci	case VGT_COMPUTE_INDEX:
32538c2ecf20Sopenharmony_ci	case VGT_COMPUTE_THREAD_GROUP_SIZE:
32548c2ecf20Sopenharmony_ci	case VGT_HS_OFFCHIP_PARAM:
32558c2ecf20Sopenharmony_ci	case PA_CL_ENHANCE:
32568c2ecf20Sopenharmony_ci	case PA_SU_LINE_STIPPLE_VALUE:
32578c2ecf20Sopenharmony_ci	case PA_SC_LINE_STIPPLE_STATE:
32588c2ecf20Sopenharmony_ci	case PA_SC_ENHANCE:
32598c2ecf20Sopenharmony_ci	case SQ_DYN_GPR_CNTL_PS_FLUSH_REQ:
32608c2ecf20Sopenharmony_ci	case SQ_DYN_GPR_SIMD_LOCK_EN:
32618c2ecf20Sopenharmony_ci	case SQ_CONFIG:
32628c2ecf20Sopenharmony_ci	case SQ_GPR_RESOURCE_MGMT_1:
32638c2ecf20Sopenharmony_ci	case SQ_GLOBAL_GPR_RESOURCE_MGMT_1:
32648c2ecf20Sopenharmony_ci	case SQ_GLOBAL_GPR_RESOURCE_MGMT_2:
32658c2ecf20Sopenharmony_ci	case SQ_CONST_MEM_BASE:
32668c2ecf20Sopenharmony_ci	case SQ_STATIC_THREAD_MGMT_1:
32678c2ecf20Sopenharmony_ci	case SQ_STATIC_THREAD_MGMT_2:
32688c2ecf20Sopenharmony_ci	case SQ_STATIC_THREAD_MGMT_3:
32698c2ecf20Sopenharmony_ci	case SPI_CONFIG_CNTL:
32708c2ecf20Sopenharmony_ci	case SPI_CONFIG_CNTL_1:
32718c2ecf20Sopenharmony_ci	case TA_CNTL_AUX:
32728c2ecf20Sopenharmony_ci	case DB_DEBUG:
32738c2ecf20Sopenharmony_ci	case DB_DEBUG2:
32748c2ecf20Sopenharmony_ci	case DB_DEBUG3:
32758c2ecf20Sopenharmony_ci	case DB_DEBUG4:
32768c2ecf20Sopenharmony_ci	case DB_WATERMARKS:
32778c2ecf20Sopenharmony_ci	case TD_PS_BORDER_COLOR_INDEX:
32788c2ecf20Sopenharmony_ci	case TD_PS_BORDER_COLOR_RED:
32798c2ecf20Sopenharmony_ci	case TD_PS_BORDER_COLOR_GREEN:
32808c2ecf20Sopenharmony_ci	case TD_PS_BORDER_COLOR_BLUE:
32818c2ecf20Sopenharmony_ci	case TD_PS_BORDER_COLOR_ALPHA:
32828c2ecf20Sopenharmony_ci	case TD_VS_BORDER_COLOR_INDEX:
32838c2ecf20Sopenharmony_ci	case TD_VS_BORDER_COLOR_RED:
32848c2ecf20Sopenharmony_ci	case TD_VS_BORDER_COLOR_GREEN:
32858c2ecf20Sopenharmony_ci	case TD_VS_BORDER_COLOR_BLUE:
32868c2ecf20Sopenharmony_ci	case TD_VS_BORDER_COLOR_ALPHA:
32878c2ecf20Sopenharmony_ci	case TD_GS_BORDER_COLOR_INDEX:
32888c2ecf20Sopenharmony_ci	case TD_GS_BORDER_COLOR_RED:
32898c2ecf20Sopenharmony_ci	case TD_GS_BORDER_COLOR_GREEN:
32908c2ecf20Sopenharmony_ci	case TD_GS_BORDER_COLOR_BLUE:
32918c2ecf20Sopenharmony_ci	case TD_GS_BORDER_COLOR_ALPHA:
32928c2ecf20Sopenharmony_ci	case TD_HS_BORDER_COLOR_INDEX:
32938c2ecf20Sopenharmony_ci	case TD_HS_BORDER_COLOR_RED:
32948c2ecf20Sopenharmony_ci	case TD_HS_BORDER_COLOR_GREEN:
32958c2ecf20Sopenharmony_ci	case TD_HS_BORDER_COLOR_BLUE:
32968c2ecf20Sopenharmony_ci	case TD_HS_BORDER_COLOR_ALPHA:
32978c2ecf20Sopenharmony_ci	case TD_LS_BORDER_COLOR_INDEX:
32988c2ecf20Sopenharmony_ci	case TD_LS_BORDER_COLOR_RED:
32998c2ecf20Sopenharmony_ci	case TD_LS_BORDER_COLOR_GREEN:
33008c2ecf20Sopenharmony_ci	case TD_LS_BORDER_COLOR_BLUE:
33018c2ecf20Sopenharmony_ci	case TD_LS_BORDER_COLOR_ALPHA:
33028c2ecf20Sopenharmony_ci	case TD_CS_BORDER_COLOR_INDEX:
33038c2ecf20Sopenharmony_ci	case TD_CS_BORDER_COLOR_RED:
33048c2ecf20Sopenharmony_ci	case TD_CS_BORDER_COLOR_GREEN:
33058c2ecf20Sopenharmony_ci	case TD_CS_BORDER_COLOR_BLUE:
33068c2ecf20Sopenharmony_ci	case TD_CS_BORDER_COLOR_ALPHA:
33078c2ecf20Sopenharmony_ci	case SQ_ESGS_RING_SIZE:
33088c2ecf20Sopenharmony_ci	case SQ_GSVS_RING_SIZE:
33098c2ecf20Sopenharmony_ci	case SQ_ESTMP_RING_SIZE:
33108c2ecf20Sopenharmony_ci	case SQ_GSTMP_RING_SIZE:
33118c2ecf20Sopenharmony_ci	case SQ_HSTMP_RING_SIZE:
33128c2ecf20Sopenharmony_ci	case SQ_LSTMP_RING_SIZE:
33138c2ecf20Sopenharmony_ci	case SQ_PSTMP_RING_SIZE:
33148c2ecf20Sopenharmony_ci	case SQ_VSTMP_RING_SIZE:
33158c2ecf20Sopenharmony_ci	case SQ_ESGS_RING_ITEMSIZE:
33168c2ecf20Sopenharmony_ci	case SQ_ESTMP_RING_ITEMSIZE:
33178c2ecf20Sopenharmony_ci	case SQ_GSTMP_RING_ITEMSIZE:
33188c2ecf20Sopenharmony_ci	case SQ_GSVS_RING_ITEMSIZE:
33198c2ecf20Sopenharmony_ci	case SQ_GS_VERT_ITEMSIZE:
33208c2ecf20Sopenharmony_ci	case SQ_GS_VERT_ITEMSIZE_1:
33218c2ecf20Sopenharmony_ci	case SQ_GS_VERT_ITEMSIZE_2:
33228c2ecf20Sopenharmony_ci	case SQ_GS_VERT_ITEMSIZE_3:
33238c2ecf20Sopenharmony_ci	case SQ_GSVS_RING_OFFSET_1:
33248c2ecf20Sopenharmony_ci	case SQ_GSVS_RING_OFFSET_2:
33258c2ecf20Sopenharmony_ci	case SQ_GSVS_RING_OFFSET_3:
33268c2ecf20Sopenharmony_ci	case SQ_HSTMP_RING_ITEMSIZE:
33278c2ecf20Sopenharmony_ci	case SQ_LSTMP_RING_ITEMSIZE:
33288c2ecf20Sopenharmony_ci	case SQ_PSTMP_RING_ITEMSIZE:
33298c2ecf20Sopenharmony_ci	case SQ_VSTMP_RING_ITEMSIZE:
33308c2ecf20Sopenharmony_ci	case VGT_TF_RING_SIZE:
33318c2ecf20Sopenharmony_ci	case SQ_ESGS_RING_BASE:
33328c2ecf20Sopenharmony_ci	case SQ_GSVS_RING_BASE:
33338c2ecf20Sopenharmony_ci	case SQ_ESTMP_RING_BASE:
33348c2ecf20Sopenharmony_ci	case SQ_GSTMP_RING_BASE:
33358c2ecf20Sopenharmony_ci	case SQ_HSTMP_RING_BASE:
33368c2ecf20Sopenharmony_ci	case SQ_LSTMP_RING_BASE:
33378c2ecf20Sopenharmony_ci	case SQ_PSTMP_RING_BASE:
33388c2ecf20Sopenharmony_ci	case SQ_VSTMP_RING_BASE:
33398c2ecf20Sopenharmony_ci	case CAYMAN_VGT_OFFCHIP_LDS_BASE:
33408c2ecf20Sopenharmony_ci	case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS:
33418c2ecf20Sopenharmony_ci		return true;
33428c2ecf20Sopenharmony_ci	default:
33438c2ecf20Sopenharmony_ci		DRM_ERROR("Invalid register 0x%x in CS\n", reg);
33448c2ecf20Sopenharmony_ci		return false;
33458c2ecf20Sopenharmony_ci	}
33468c2ecf20Sopenharmony_ci}
33478c2ecf20Sopenharmony_ci
33488c2ecf20Sopenharmony_cistatic int evergreen_vm_packet3_check(struct radeon_device *rdev,
33498c2ecf20Sopenharmony_ci				      u32 *ib, struct radeon_cs_packet *pkt)
33508c2ecf20Sopenharmony_ci{
33518c2ecf20Sopenharmony_ci	u32 idx = pkt->idx + 1;
33528c2ecf20Sopenharmony_ci	u32 idx_value = ib[idx];
33538c2ecf20Sopenharmony_ci	u32 start_reg, end_reg, reg, i;
33548c2ecf20Sopenharmony_ci	u32 command, info;
33558c2ecf20Sopenharmony_ci
33568c2ecf20Sopenharmony_ci	switch (pkt->opcode) {
33578c2ecf20Sopenharmony_ci	case PACKET3_NOP:
33588c2ecf20Sopenharmony_ci		break;
33598c2ecf20Sopenharmony_ci	case PACKET3_SET_BASE:
33608c2ecf20Sopenharmony_ci		if (idx_value != 1) {
33618c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET_BASE");
33628c2ecf20Sopenharmony_ci			return -EINVAL;
33638c2ecf20Sopenharmony_ci		}
33648c2ecf20Sopenharmony_ci		break;
33658c2ecf20Sopenharmony_ci	case PACKET3_CLEAR_STATE:
33668c2ecf20Sopenharmony_ci	case PACKET3_INDEX_BUFFER_SIZE:
33678c2ecf20Sopenharmony_ci	case PACKET3_DISPATCH_DIRECT:
33688c2ecf20Sopenharmony_ci	case PACKET3_DISPATCH_INDIRECT:
33698c2ecf20Sopenharmony_ci	case PACKET3_MODE_CONTROL:
33708c2ecf20Sopenharmony_ci	case PACKET3_SET_PREDICATION:
33718c2ecf20Sopenharmony_ci	case PACKET3_COND_EXEC:
33728c2ecf20Sopenharmony_ci	case PACKET3_PRED_EXEC:
33738c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDIRECT:
33748c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX_INDIRECT:
33758c2ecf20Sopenharmony_ci	case PACKET3_INDEX_BASE:
33768c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX_2:
33778c2ecf20Sopenharmony_ci	case PACKET3_CONTEXT_CONTROL:
33788c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX_OFFSET:
33798c2ecf20Sopenharmony_ci	case PACKET3_INDEX_TYPE:
33808c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX:
33818c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX_AUTO:
33828c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX_IMMD:
33838c2ecf20Sopenharmony_ci	case PACKET3_NUM_INSTANCES:
33848c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX_MULTI_AUTO:
33858c2ecf20Sopenharmony_ci	case PACKET3_STRMOUT_BUFFER_UPDATE:
33868c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX_OFFSET_2:
33878c2ecf20Sopenharmony_ci	case PACKET3_DRAW_INDEX_MULTI_ELEMENT:
33888c2ecf20Sopenharmony_ci	case PACKET3_MPEG_INDEX:
33898c2ecf20Sopenharmony_ci	case PACKET3_WAIT_REG_MEM:
33908c2ecf20Sopenharmony_ci	case PACKET3_MEM_WRITE:
33918c2ecf20Sopenharmony_ci	case PACKET3_PFP_SYNC_ME:
33928c2ecf20Sopenharmony_ci	case PACKET3_SURFACE_SYNC:
33938c2ecf20Sopenharmony_ci	case PACKET3_EVENT_WRITE:
33948c2ecf20Sopenharmony_ci	case PACKET3_EVENT_WRITE_EOP:
33958c2ecf20Sopenharmony_ci	case PACKET3_EVENT_WRITE_EOS:
33968c2ecf20Sopenharmony_ci	case PACKET3_SET_CONTEXT_REG:
33978c2ecf20Sopenharmony_ci	case PACKET3_SET_BOOL_CONST:
33988c2ecf20Sopenharmony_ci	case PACKET3_SET_LOOP_CONST:
33998c2ecf20Sopenharmony_ci	case PACKET3_SET_RESOURCE:
34008c2ecf20Sopenharmony_ci	case PACKET3_SET_SAMPLER:
34018c2ecf20Sopenharmony_ci	case PACKET3_SET_CTL_CONST:
34028c2ecf20Sopenharmony_ci	case PACKET3_SET_RESOURCE_OFFSET:
34038c2ecf20Sopenharmony_ci	case PACKET3_SET_CONTEXT_REG_INDIRECT:
34048c2ecf20Sopenharmony_ci	case PACKET3_SET_RESOURCE_INDIRECT:
34058c2ecf20Sopenharmony_ci	case CAYMAN_PACKET3_DEALLOC_STATE:
34068c2ecf20Sopenharmony_ci		break;
34078c2ecf20Sopenharmony_ci	case PACKET3_COND_WRITE:
34088c2ecf20Sopenharmony_ci		if (idx_value & 0x100) {
34098c2ecf20Sopenharmony_ci			reg = ib[idx + 5] * 4;
34108c2ecf20Sopenharmony_ci			if (!evergreen_vm_reg_valid(reg))
34118c2ecf20Sopenharmony_ci				return -EINVAL;
34128c2ecf20Sopenharmony_ci		}
34138c2ecf20Sopenharmony_ci		break;
34148c2ecf20Sopenharmony_ci	case PACKET3_COPY_DW:
34158c2ecf20Sopenharmony_ci		if (idx_value & 0x2) {
34168c2ecf20Sopenharmony_ci			reg = ib[idx + 3] * 4;
34178c2ecf20Sopenharmony_ci			if (!evergreen_vm_reg_valid(reg))
34188c2ecf20Sopenharmony_ci				return -EINVAL;
34198c2ecf20Sopenharmony_ci		}
34208c2ecf20Sopenharmony_ci		break;
34218c2ecf20Sopenharmony_ci	case PACKET3_SET_CONFIG_REG:
34228c2ecf20Sopenharmony_ci		start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START;
34238c2ecf20Sopenharmony_ci		end_reg = 4 * pkt->count + start_reg - 4;
34248c2ecf20Sopenharmony_ci		if ((start_reg < PACKET3_SET_CONFIG_REG_START) ||
34258c2ecf20Sopenharmony_ci		    (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
34268c2ecf20Sopenharmony_ci		    (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
34278c2ecf20Sopenharmony_ci			DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
34288c2ecf20Sopenharmony_ci			return -EINVAL;
34298c2ecf20Sopenharmony_ci		}
34308c2ecf20Sopenharmony_ci		for (i = 0; i < pkt->count; i++) {
34318c2ecf20Sopenharmony_ci			reg = start_reg + (4 * i);
34328c2ecf20Sopenharmony_ci			if (!evergreen_vm_reg_valid(reg))
34338c2ecf20Sopenharmony_ci				return -EINVAL;
34348c2ecf20Sopenharmony_ci		}
34358c2ecf20Sopenharmony_ci		break;
34368c2ecf20Sopenharmony_ci	case PACKET3_CP_DMA:
34378c2ecf20Sopenharmony_ci		command = ib[idx + 4];
34388c2ecf20Sopenharmony_ci		info = ib[idx + 1];
34398c2ecf20Sopenharmony_ci		if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */
34408c2ecf20Sopenharmony_ci		    (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */
34418c2ecf20Sopenharmony_ci		    ((((info & 0x00300000) >> 20) == 0) &&
34428c2ecf20Sopenharmony_ci		     (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */
34438c2ecf20Sopenharmony_ci		    ((((info & 0x60000000) >> 29) == 0) &&
34448c2ecf20Sopenharmony_ci		     (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */
34458c2ecf20Sopenharmony_ci			/* non mem to mem copies requires dw aligned count */
34468c2ecf20Sopenharmony_ci			if ((command & 0x1fffff) % 4) {
34478c2ecf20Sopenharmony_ci				DRM_ERROR("CP DMA command requires dw count alignment\n");
34488c2ecf20Sopenharmony_ci				return -EINVAL;
34498c2ecf20Sopenharmony_ci			}
34508c2ecf20Sopenharmony_ci		}
34518c2ecf20Sopenharmony_ci		if (command & PACKET3_CP_DMA_CMD_SAS) {
34528c2ecf20Sopenharmony_ci			/* src address space is register */
34538c2ecf20Sopenharmony_ci			if (((info & 0x60000000) >> 29) == 0) {
34548c2ecf20Sopenharmony_ci				start_reg = idx_value << 2;
34558c2ecf20Sopenharmony_ci				if (command & PACKET3_CP_DMA_CMD_SAIC) {
34568c2ecf20Sopenharmony_ci					reg = start_reg;
34578c2ecf20Sopenharmony_ci					if (!evergreen_vm_reg_valid(reg)) {
34588c2ecf20Sopenharmony_ci						DRM_ERROR("CP DMA Bad SRC register\n");
34598c2ecf20Sopenharmony_ci						return -EINVAL;
34608c2ecf20Sopenharmony_ci					}
34618c2ecf20Sopenharmony_ci				} else {
34628c2ecf20Sopenharmony_ci					for (i = 0; i < (command & 0x1fffff); i++) {
34638c2ecf20Sopenharmony_ci						reg = start_reg + (4 * i);
34648c2ecf20Sopenharmony_ci						if (!evergreen_vm_reg_valid(reg)) {
34658c2ecf20Sopenharmony_ci							DRM_ERROR("CP DMA Bad SRC register\n");
34668c2ecf20Sopenharmony_ci							return -EINVAL;
34678c2ecf20Sopenharmony_ci						}
34688c2ecf20Sopenharmony_ci					}
34698c2ecf20Sopenharmony_ci				}
34708c2ecf20Sopenharmony_ci			}
34718c2ecf20Sopenharmony_ci		}
34728c2ecf20Sopenharmony_ci		if (command & PACKET3_CP_DMA_CMD_DAS) {
34738c2ecf20Sopenharmony_ci			/* dst address space is register */
34748c2ecf20Sopenharmony_ci			if (((info & 0x00300000) >> 20) == 0) {
34758c2ecf20Sopenharmony_ci				start_reg = ib[idx + 2];
34768c2ecf20Sopenharmony_ci				if (command & PACKET3_CP_DMA_CMD_DAIC) {
34778c2ecf20Sopenharmony_ci					reg = start_reg;
34788c2ecf20Sopenharmony_ci					if (!evergreen_vm_reg_valid(reg)) {
34798c2ecf20Sopenharmony_ci						DRM_ERROR("CP DMA Bad DST register\n");
34808c2ecf20Sopenharmony_ci						return -EINVAL;
34818c2ecf20Sopenharmony_ci					}
34828c2ecf20Sopenharmony_ci				} else {
34838c2ecf20Sopenharmony_ci					for (i = 0; i < (command & 0x1fffff); i++) {
34848c2ecf20Sopenharmony_ci						reg = start_reg + (4 * i);
34858c2ecf20Sopenharmony_ci						if (!evergreen_vm_reg_valid(reg)) {
34868c2ecf20Sopenharmony_ci							DRM_ERROR("CP DMA Bad DST register\n");
34878c2ecf20Sopenharmony_ci							return -EINVAL;
34888c2ecf20Sopenharmony_ci						}
34898c2ecf20Sopenharmony_ci					}
34908c2ecf20Sopenharmony_ci				}
34918c2ecf20Sopenharmony_ci			}
34928c2ecf20Sopenharmony_ci		}
34938c2ecf20Sopenharmony_ci		break;
34948c2ecf20Sopenharmony_ci	case PACKET3_SET_APPEND_CNT: {
34958c2ecf20Sopenharmony_ci		uint32_t areg;
34968c2ecf20Sopenharmony_ci		uint32_t allowed_reg_base;
34978c2ecf20Sopenharmony_ci
34988c2ecf20Sopenharmony_ci		if (pkt->count != 2) {
34998c2ecf20Sopenharmony_ci			DRM_ERROR("bad SET_APPEND_CNT (invalid count)\n");
35008c2ecf20Sopenharmony_ci			return -EINVAL;
35018c2ecf20Sopenharmony_ci		}
35028c2ecf20Sopenharmony_ci
35038c2ecf20Sopenharmony_ci		allowed_reg_base = GDS_APPEND_COUNT_0;
35048c2ecf20Sopenharmony_ci		allowed_reg_base -= PACKET3_SET_CONTEXT_REG_START;
35058c2ecf20Sopenharmony_ci		allowed_reg_base >>= 2;
35068c2ecf20Sopenharmony_ci
35078c2ecf20Sopenharmony_ci		areg = idx_value >> 16;
35088c2ecf20Sopenharmony_ci		if (areg < allowed_reg_base || areg > (allowed_reg_base + 11)) {
35098c2ecf20Sopenharmony_ci			DRM_ERROR("forbidden register for append cnt 0x%08x at %d\n",
35108c2ecf20Sopenharmony_ci				  areg, idx);
35118c2ecf20Sopenharmony_ci			return -EINVAL;
35128c2ecf20Sopenharmony_ci		}
35138c2ecf20Sopenharmony_ci		break;
35148c2ecf20Sopenharmony_ci	}
35158c2ecf20Sopenharmony_ci	default:
35168c2ecf20Sopenharmony_ci		return -EINVAL;
35178c2ecf20Sopenharmony_ci	}
35188c2ecf20Sopenharmony_ci	return 0;
35198c2ecf20Sopenharmony_ci}
35208c2ecf20Sopenharmony_ci
35218c2ecf20Sopenharmony_ciint evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
35228c2ecf20Sopenharmony_ci{
35238c2ecf20Sopenharmony_ci	int ret = 0;
35248c2ecf20Sopenharmony_ci	u32 idx = 0;
35258c2ecf20Sopenharmony_ci	struct radeon_cs_packet pkt;
35268c2ecf20Sopenharmony_ci
35278c2ecf20Sopenharmony_ci	do {
35288c2ecf20Sopenharmony_ci		pkt.idx = idx;
35298c2ecf20Sopenharmony_ci		pkt.type = RADEON_CP_PACKET_GET_TYPE(ib->ptr[idx]);
35308c2ecf20Sopenharmony_ci		pkt.count = RADEON_CP_PACKET_GET_COUNT(ib->ptr[idx]);
35318c2ecf20Sopenharmony_ci		pkt.one_reg_wr = 0;
35328c2ecf20Sopenharmony_ci		switch (pkt.type) {
35338c2ecf20Sopenharmony_ci		case RADEON_PACKET_TYPE0:
35348c2ecf20Sopenharmony_ci			dev_err(rdev->dev, "Packet0 not allowed!\n");
35358c2ecf20Sopenharmony_ci			ret = -EINVAL;
35368c2ecf20Sopenharmony_ci			break;
35378c2ecf20Sopenharmony_ci		case RADEON_PACKET_TYPE2:
35388c2ecf20Sopenharmony_ci			idx += 1;
35398c2ecf20Sopenharmony_ci			break;
35408c2ecf20Sopenharmony_ci		case RADEON_PACKET_TYPE3:
35418c2ecf20Sopenharmony_ci			pkt.opcode = RADEON_CP_PACKET3_GET_OPCODE(ib->ptr[idx]);
35428c2ecf20Sopenharmony_ci			ret = evergreen_vm_packet3_check(rdev, ib->ptr, &pkt);
35438c2ecf20Sopenharmony_ci			idx += pkt.count + 2;
35448c2ecf20Sopenharmony_ci			break;
35458c2ecf20Sopenharmony_ci		default:
35468c2ecf20Sopenharmony_ci			dev_err(rdev->dev, "Unknown packet type %d !\n", pkt.type);
35478c2ecf20Sopenharmony_ci			ret = -EINVAL;
35488c2ecf20Sopenharmony_ci			break;
35498c2ecf20Sopenharmony_ci		}
35508c2ecf20Sopenharmony_ci		if (ret)
35518c2ecf20Sopenharmony_ci			break;
35528c2ecf20Sopenharmony_ci	} while (idx < ib->length_dw);
35538c2ecf20Sopenharmony_ci
35548c2ecf20Sopenharmony_ci	return ret;
35558c2ecf20Sopenharmony_ci}
35568c2ecf20Sopenharmony_ci
35578c2ecf20Sopenharmony_ci/**
35588c2ecf20Sopenharmony_ci * evergreen_dma_ib_parse() - parse the DMA IB for VM
35598c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer
35608c2ecf20Sopenharmony_ci * @ib:	radeon_ib pointer
35618c2ecf20Sopenharmony_ci *
35628c2ecf20Sopenharmony_ci * Parses the DMA IB from the VM CS ioctl
35638c2ecf20Sopenharmony_ci * checks for errors. (Cayman-SI)
35648c2ecf20Sopenharmony_ci * Returns 0 for success and an error on failure.
35658c2ecf20Sopenharmony_ci **/
35668c2ecf20Sopenharmony_ciint evergreen_dma_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
35678c2ecf20Sopenharmony_ci{
35688c2ecf20Sopenharmony_ci	u32 idx = 0;
35698c2ecf20Sopenharmony_ci	u32 header, cmd, count, sub_cmd;
35708c2ecf20Sopenharmony_ci
35718c2ecf20Sopenharmony_ci	do {
35728c2ecf20Sopenharmony_ci		header = ib->ptr[idx];
35738c2ecf20Sopenharmony_ci		cmd = GET_DMA_CMD(header);
35748c2ecf20Sopenharmony_ci		count = GET_DMA_COUNT(header);
35758c2ecf20Sopenharmony_ci		sub_cmd = GET_DMA_SUB_CMD(header);
35768c2ecf20Sopenharmony_ci
35778c2ecf20Sopenharmony_ci		switch (cmd) {
35788c2ecf20Sopenharmony_ci		case DMA_PACKET_WRITE:
35798c2ecf20Sopenharmony_ci			switch (sub_cmd) {
35808c2ecf20Sopenharmony_ci			/* tiled */
35818c2ecf20Sopenharmony_ci			case 8:
35828c2ecf20Sopenharmony_ci				idx += count + 7;
35838c2ecf20Sopenharmony_ci				break;
35848c2ecf20Sopenharmony_ci			/* linear */
35858c2ecf20Sopenharmony_ci			case 0:
35868c2ecf20Sopenharmony_ci				idx += count + 3;
35878c2ecf20Sopenharmony_ci				break;
35888c2ecf20Sopenharmony_ci			default:
35898c2ecf20Sopenharmony_ci				DRM_ERROR("bad DMA_PACKET_WRITE [%6d] 0x%08x sub cmd is not 0 or 8\n", idx, ib->ptr[idx]);
35908c2ecf20Sopenharmony_ci				return -EINVAL;
35918c2ecf20Sopenharmony_ci			}
35928c2ecf20Sopenharmony_ci			break;
35938c2ecf20Sopenharmony_ci		case DMA_PACKET_COPY:
35948c2ecf20Sopenharmony_ci			switch (sub_cmd) {
35958c2ecf20Sopenharmony_ci			/* Copy L2L, DW aligned */
35968c2ecf20Sopenharmony_ci			case 0x00:
35978c2ecf20Sopenharmony_ci				idx += 5;
35988c2ecf20Sopenharmony_ci				break;
35998c2ecf20Sopenharmony_ci			/* Copy L2T/T2L */
36008c2ecf20Sopenharmony_ci			case 0x08:
36018c2ecf20Sopenharmony_ci				idx += 9;
36028c2ecf20Sopenharmony_ci				break;
36038c2ecf20Sopenharmony_ci			/* Copy L2L, byte aligned */
36048c2ecf20Sopenharmony_ci			case 0x40:
36058c2ecf20Sopenharmony_ci				idx += 5;
36068c2ecf20Sopenharmony_ci				break;
36078c2ecf20Sopenharmony_ci			/* Copy L2L, partial */
36088c2ecf20Sopenharmony_ci			case 0x41:
36098c2ecf20Sopenharmony_ci				idx += 9;
36108c2ecf20Sopenharmony_ci				break;
36118c2ecf20Sopenharmony_ci			/* Copy L2L, DW aligned, broadcast */
36128c2ecf20Sopenharmony_ci			case 0x44:
36138c2ecf20Sopenharmony_ci				idx += 7;
36148c2ecf20Sopenharmony_ci				break;
36158c2ecf20Sopenharmony_ci			/* Copy L2T Frame to Field */
36168c2ecf20Sopenharmony_ci			case 0x48:
36178c2ecf20Sopenharmony_ci				idx += 10;
36188c2ecf20Sopenharmony_ci				break;
36198c2ecf20Sopenharmony_ci			/* Copy L2T/T2L, partial */
36208c2ecf20Sopenharmony_ci			case 0x49:
36218c2ecf20Sopenharmony_ci				idx += 12;
36228c2ecf20Sopenharmony_ci				break;
36238c2ecf20Sopenharmony_ci			/* Copy L2T broadcast */
36248c2ecf20Sopenharmony_ci			case 0x4b:
36258c2ecf20Sopenharmony_ci				idx += 10;
36268c2ecf20Sopenharmony_ci				break;
36278c2ecf20Sopenharmony_ci			/* Copy L2T/T2L (tile units) */
36288c2ecf20Sopenharmony_ci			case 0x4c:
36298c2ecf20Sopenharmony_ci				idx += 9;
36308c2ecf20Sopenharmony_ci				break;
36318c2ecf20Sopenharmony_ci			/* Copy T2T, partial (tile units) */
36328c2ecf20Sopenharmony_ci			case 0x4d:
36338c2ecf20Sopenharmony_ci				idx += 13;
36348c2ecf20Sopenharmony_ci				break;
36358c2ecf20Sopenharmony_ci			/* Copy L2T broadcast (tile units) */
36368c2ecf20Sopenharmony_ci			case 0x4f:
36378c2ecf20Sopenharmony_ci				idx += 10;
36388c2ecf20Sopenharmony_ci				break;
36398c2ecf20Sopenharmony_ci			default:
36408c2ecf20Sopenharmony_ci				DRM_ERROR("bad DMA_PACKET_COPY [%6d] 0x%08x invalid sub cmd\n", idx, ib->ptr[idx]);
36418c2ecf20Sopenharmony_ci				return -EINVAL;
36428c2ecf20Sopenharmony_ci			}
36438c2ecf20Sopenharmony_ci			break;
36448c2ecf20Sopenharmony_ci		case DMA_PACKET_CONSTANT_FILL:
36458c2ecf20Sopenharmony_ci			idx += 4;
36468c2ecf20Sopenharmony_ci			break;
36478c2ecf20Sopenharmony_ci		case DMA_PACKET_NOP:
36488c2ecf20Sopenharmony_ci			idx += 1;
36498c2ecf20Sopenharmony_ci			break;
36508c2ecf20Sopenharmony_ci		default:
36518c2ecf20Sopenharmony_ci			DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx);
36528c2ecf20Sopenharmony_ci			return -EINVAL;
36538c2ecf20Sopenharmony_ci		}
36548c2ecf20Sopenharmony_ci	} while (idx < ib->length_dw);
36558c2ecf20Sopenharmony_ci
36568c2ecf20Sopenharmony_ci	return 0;
36578c2ecf20Sopenharmony_ci}
3658