LCOV - code coverage report
Current view: top level - dev/pci/drm/radeon - r600_cs.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1316 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 23 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2008 Advanced Micro Devices, Inc.
       3             :  * Copyright 2008 Red Hat Inc.
       4             :  * Copyright 2009 Jerome Glisse.
       5             :  *
       6             :  * Permission is hereby granted, free of charge, to any person obtaining a
       7             :  * copy of this software and associated documentation files (the "Software"),
       8             :  * to deal in the Software without restriction, including without limitation
       9             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      10             :  * and/or sell copies of the Software, and to permit persons to whom the
      11             :  * Software is furnished to do so, subject to the following conditions:
      12             :  *
      13             :  * The above copyright notice and this permission notice shall be included in
      14             :  * all copies or substantial portions of the Software.
      15             :  *
      16             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      17             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      18             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      19             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      20             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      21             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      22             :  * OTHER DEALINGS IN THE SOFTWARE.
      23             :  *
      24             :  * Authors: Dave Airlie
      25             :  *          Alex Deucher
      26             :  *          Jerome Glisse
      27             :  */
      28             : #include <dev/pci/drm/drmP.h>
      29             : #include "radeon.h"
      30             : #include "r600d.h"
      31             : #include "r600_reg_safe.h"
      32             : 
      33             : static int r600_nomm;
      34             : extern void r600_cs_legacy_get_tiling_conf(struct drm_device *dev, u32 *npipes, u32 *nbanks, u32 *group_size);
      35             : 
      36             : 
      37             : struct r600_cs_track {
      38             :         /* configuration we miror so that we use same code btw kms/ums */
      39             :         u32                     group_size;
      40             :         u32                     nbanks;
      41             :         u32                     npipes;
      42             :         /* value we track */
      43             :         u32                     sq_config;
      44             :         u32                     log_nsamples;
      45             :         u32                     nsamples;
      46             :         u32                     cb_color_base_last[8];
      47             :         struct radeon_bo        *cb_color_bo[8];
      48             :         u64                     cb_color_bo_mc[8];
      49             :         u64                     cb_color_bo_offset[8];
      50             :         struct radeon_bo        *cb_color_frag_bo[8];
      51             :         u64                     cb_color_frag_offset[8];
      52             :         struct radeon_bo        *cb_color_tile_bo[8];
      53             :         u64                     cb_color_tile_offset[8];
      54             :         u32                     cb_color_mask[8];
      55             :         u32                     cb_color_info[8];
      56             :         u32                     cb_color_view[8];
      57             :         u32                     cb_color_size_idx[8]; /* unused */
      58             :         u32                     cb_target_mask;
      59             :         u32                     cb_shader_mask;  /* unused */
      60             :         bool                    is_resolve;
      61             :         u32                     cb_color_size[8];
      62             :         u32                     vgt_strmout_en;
      63             :         u32                     vgt_strmout_buffer_en;
      64             :         struct radeon_bo        *vgt_strmout_bo[4];
      65             :         u64                     vgt_strmout_bo_mc[4]; /* unused */
      66             :         u32                     vgt_strmout_bo_offset[4];
      67             :         u32                     vgt_strmout_size[4];
      68             :         u32                     db_depth_control;
      69             :         u32                     db_depth_info;
      70             :         u32                     db_depth_size_idx;
      71             :         u32                     db_depth_view;
      72             :         u32                     db_depth_size;
      73             :         u32                     db_offset;
      74             :         struct radeon_bo        *db_bo;
      75             :         u64                     db_bo_mc;
      76             :         bool                    sx_misc_kill_all_prims;
      77             :         bool                    cb_dirty;
      78             :         bool                    db_dirty;
      79             :         bool                    streamout_dirty;
      80             :         struct radeon_bo        *htile_bo;
      81             :         u64                     htile_offset;
      82             :         u32                     htile_surface;
      83             : };
      84             : 
      85             : #define FMT_8_BIT(fmt, vc)   [fmt] = { 1, 1, 1, vc, CHIP_R600 }
      86             : #define FMT_16_BIT(fmt, vc)  [fmt] = { 1, 1, 2, vc, CHIP_R600 }
      87             : #define FMT_24_BIT(fmt)      [fmt] = { 1, 1, 4,  0, CHIP_R600 }
      88             : #define FMT_32_BIT(fmt, vc)  [fmt] = { 1, 1, 4, vc, CHIP_R600 }
      89             : #define FMT_48_BIT(fmt)      [fmt] = { 1, 1, 8,  0, CHIP_R600 }
      90             : #define FMT_64_BIT(fmt, vc)  [fmt] = { 1, 1, 8, vc, CHIP_R600 }
      91             : #define FMT_96_BIT(fmt)      [fmt] = { 1, 1, 12, 0, CHIP_R600 }
      92             : #define FMT_128_BIT(fmt, vc) [fmt] = { 1, 1, 16,vc, CHIP_R600 }
      93             : 
      94             : struct gpu_formats {
      95             :         unsigned blockwidth;
      96             :         unsigned blockheight;
      97             :         unsigned blocksize;
      98             :         unsigned valid_color;
      99             :         enum radeon_family min_family;
     100             : };
     101             : 
     102             : static const struct gpu_formats color_formats_table[] = {
     103             :         /* 8 bit */
     104             :         FMT_8_BIT(V_038004_COLOR_8, 1),
     105             :         FMT_8_BIT(V_038004_COLOR_4_4, 1),
     106             :         FMT_8_BIT(V_038004_COLOR_3_3_2, 1),
     107             :         FMT_8_BIT(V_038004_FMT_1, 0),
     108             : 
     109             :         /* 16-bit */
     110             :         FMT_16_BIT(V_038004_COLOR_16, 1),
     111             :         FMT_16_BIT(V_038004_COLOR_16_FLOAT, 1),
     112             :         FMT_16_BIT(V_038004_COLOR_8_8, 1),
     113             :         FMT_16_BIT(V_038004_COLOR_5_6_5, 1),
     114             :         FMT_16_BIT(V_038004_COLOR_6_5_5, 1),
     115             :         FMT_16_BIT(V_038004_COLOR_1_5_5_5, 1),
     116             :         FMT_16_BIT(V_038004_COLOR_4_4_4_4, 1),
     117             :         FMT_16_BIT(V_038004_COLOR_5_5_5_1, 1),
     118             : 
     119             :         /* 24-bit */
     120             :         FMT_24_BIT(V_038004_FMT_8_8_8),
     121             : 
     122             :         /* 32-bit */
     123             :         FMT_32_BIT(V_038004_COLOR_32, 1),
     124             :         FMT_32_BIT(V_038004_COLOR_32_FLOAT, 1),
     125             :         FMT_32_BIT(V_038004_COLOR_16_16, 1),
     126             :         FMT_32_BIT(V_038004_COLOR_16_16_FLOAT, 1),
     127             :         FMT_32_BIT(V_038004_COLOR_8_24, 1),
     128             :         FMT_32_BIT(V_038004_COLOR_8_24_FLOAT, 1),
     129             :         FMT_32_BIT(V_038004_COLOR_24_8, 1),
     130             :         FMT_32_BIT(V_038004_COLOR_24_8_FLOAT, 1),
     131             :         FMT_32_BIT(V_038004_COLOR_10_11_11, 1),
     132             :         FMT_32_BIT(V_038004_COLOR_10_11_11_FLOAT, 1),
     133             :         FMT_32_BIT(V_038004_COLOR_11_11_10, 1),
     134             :         FMT_32_BIT(V_038004_COLOR_11_11_10_FLOAT, 1),
     135             :         FMT_32_BIT(V_038004_COLOR_2_10_10_10, 1),
     136             :         FMT_32_BIT(V_038004_COLOR_8_8_8_8, 1),
     137             :         FMT_32_BIT(V_038004_COLOR_10_10_10_2, 1),
     138             :         FMT_32_BIT(V_038004_FMT_5_9_9_9_SHAREDEXP, 0),
     139             :         FMT_32_BIT(V_038004_FMT_32_AS_8, 0),
     140             :         FMT_32_BIT(V_038004_FMT_32_AS_8_8, 0),
     141             : 
     142             :         /* 48-bit */
     143             :         FMT_48_BIT(V_038004_FMT_16_16_16),
     144             :         FMT_48_BIT(V_038004_FMT_16_16_16_FLOAT),
     145             : 
     146             :         /* 64-bit */
     147             :         FMT_64_BIT(V_038004_COLOR_X24_8_32_FLOAT, 1),
     148             :         FMT_64_BIT(V_038004_COLOR_32_32, 1),
     149             :         FMT_64_BIT(V_038004_COLOR_32_32_FLOAT, 1),
     150             :         FMT_64_BIT(V_038004_COLOR_16_16_16_16, 1),
     151             :         FMT_64_BIT(V_038004_COLOR_16_16_16_16_FLOAT, 1),
     152             : 
     153             :         FMT_96_BIT(V_038004_FMT_32_32_32),
     154             :         FMT_96_BIT(V_038004_FMT_32_32_32_FLOAT),
     155             : 
     156             :         /* 128-bit */
     157             :         FMT_128_BIT(V_038004_COLOR_32_32_32_32, 1),
     158             :         FMT_128_BIT(V_038004_COLOR_32_32_32_32_FLOAT, 1),
     159             : 
     160             :         [V_038004_FMT_GB_GR] = { 2, 1, 4, 0 },
     161             :         [V_038004_FMT_BG_RG] = { 2, 1, 4, 0 },
     162             : 
     163             :         /* block compressed formats */
     164             :         [V_038004_FMT_BC1] = { 4, 4, 8, 0 },
     165             :         [V_038004_FMT_BC2] = { 4, 4, 16, 0 },
     166             :         [V_038004_FMT_BC3] = { 4, 4, 16, 0 },
     167             :         [V_038004_FMT_BC4] = { 4, 4, 8, 0 },
     168             :         [V_038004_FMT_BC5] = { 4, 4, 16, 0},
     169             :         [V_038004_FMT_BC6] = { 4, 4, 16, 0, CHIP_CEDAR}, /* Evergreen-only */
     170             :         [V_038004_FMT_BC7] = { 4, 4, 16, 0, CHIP_CEDAR}, /* Evergreen-only */
     171             : 
     172             :         /* The other Evergreen formats */
     173             :         [V_038004_FMT_32_AS_32_32_32_32] = { 1, 1, 4, 0, CHIP_CEDAR},
     174             : };
     175             : 
     176           0 : bool r600_fmt_is_valid_color(u32 format)
     177             : {
     178           0 :         if (format >= ARRAY_SIZE(color_formats_table))
     179           0 :                 return false;
     180             : 
     181           0 :         if (color_formats_table[format].valid_color)
     182           0 :                 return true;
     183             : 
     184           0 :         return false;
     185           0 : }
     186             : 
     187           0 : bool r600_fmt_is_valid_texture(u32 format, enum radeon_family family)
     188             : {
     189           0 :         if (format >= ARRAY_SIZE(color_formats_table))
     190           0 :                 return false;
     191             : 
     192           0 :         if (family < color_formats_table[format].min_family)
     193           0 :                 return false;
     194             : 
     195           0 :         if (color_formats_table[format].blockwidth > 0)
     196           0 :                 return true;
     197             : 
     198           0 :         return false;
     199           0 : }
     200             : 
     201           0 : int r600_fmt_get_blocksize(u32 format)
     202             : {
     203           0 :         if (format >= ARRAY_SIZE(color_formats_table))
     204           0 :                 return 0;
     205             : 
     206           0 :         return color_formats_table[format].blocksize;
     207           0 : }
     208             : 
     209           0 : int r600_fmt_get_nblocksx(u32 format, u32 w)
     210             : {
     211             :         unsigned bw;
     212             : 
     213           0 :         if (format >= ARRAY_SIZE(color_formats_table))
     214           0 :                 return 0;
     215             : 
     216           0 :         bw = color_formats_table[format].blockwidth;
     217           0 :         if (bw == 0)
     218           0 :                 return 0;
     219             : 
     220           0 :         return (w + bw - 1) / bw;
     221           0 : }
     222             : 
     223           0 : int r600_fmt_get_nblocksy(u32 format, u32 h)
     224             : {
     225             :         unsigned bh;
     226             : 
     227           0 :         if (format >= ARRAY_SIZE(color_formats_table))
     228           0 :                 return 0;
     229             : 
     230           0 :         bh = color_formats_table[format].blockheight;
     231           0 :         if (bh == 0)
     232           0 :                 return 0;
     233             : 
     234           0 :         return (h + bh - 1) / bh;
     235           0 : }
     236             : 
     237             : struct array_mode_checker {
     238             :         int array_mode;
     239             :         u32 group_size;
     240             :         u32 nbanks;
     241             :         u32 npipes;
     242             :         u32 nsamples;
     243             :         u32 blocksize;
     244             : };
     245             : 
     246             : /* returns alignment in pixels for pitch/height/depth and bytes for base */
     247           0 : static int r600_get_array_mode_alignment(struct array_mode_checker *values,
     248             :                                                 u32 *pitch_align,
     249             :                                                 u32 *height_align,
     250             :                                                 u32 *depth_align,
     251             :                                                 u64 *base_align)
     252             : {
     253             :         u32 tile_width = 8;
     254             :         u32 tile_height = 8;
     255           0 :         u32 macro_tile_width = values->nbanks;
     256           0 :         u32 macro_tile_height = values->npipes;
     257           0 :         u32 tile_bytes = tile_width * tile_height * values->blocksize * values->nsamples;
     258           0 :         u32 macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes;
     259             : 
     260           0 :         switch (values->array_mode) {
     261             :         case ARRAY_LINEAR_GENERAL:
     262             :                 /* technically tile_width/_height for pitch/height */
     263           0 :                 *pitch_align = 1; /* tile_width */
     264           0 :                 *height_align = 1; /* tile_height */
     265           0 :                 *depth_align = 1;
     266           0 :                 *base_align = 1;
     267           0 :                 break;
     268             :         case ARRAY_LINEAR_ALIGNED:
     269           0 :                 *pitch_align = max((u32)64, (u32)(values->group_size / values->blocksize));
     270           0 :                 *height_align = 1;
     271           0 :                 *depth_align = 1;
     272           0 :                 *base_align = values->group_size;
     273           0 :                 break;
     274             :         case ARRAY_1D_TILED_THIN1:
     275           0 :                 *pitch_align = max((u32)tile_width,
     276           0 :                                    (u32)(values->group_size /
     277           0 :                                          (tile_height * values->blocksize * values->nsamples)));
     278           0 :                 *height_align = tile_height;
     279           0 :                 *depth_align = 1;
     280           0 :                 *base_align = values->group_size;
     281           0 :                 break;
     282             :         case ARRAY_2D_TILED_THIN1:
     283           0 :                 *pitch_align = max((u32)macro_tile_width * tile_width,
     284           0 :                                 (u32)((values->group_size * values->nbanks) /
     285           0 :                                 (values->blocksize * values->nsamples * tile_width)));
     286           0 :                 *height_align = macro_tile_height * tile_height;
     287           0 :                 *depth_align = 1;
     288           0 :                 *base_align = max(macro_tile_bytes,
     289           0 :                                   (*pitch_align) * values->blocksize * (*height_align) * values->nsamples);
     290           0 :                 break;
     291             :         default:
     292           0 :                 return -EINVAL;
     293             :         }
     294             : 
     295           0 :         return 0;
     296           0 : }
     297             : 
     298           0 : static void r600_cs_track_init(struct r600_cs_track *track)
     299             : {
     300             :         int i;
     301             : 
     302             :         /* assume DX9 mode */
     303           0 :         track->sq_config = DX9_CONSTS;
     304           0 :         for (i = 0; i < 8; i++) {
     305           0 :                 track->cb_color_base_last[i] = 0;
     306           0 :                 track->cb_color_size[i] = 0;
     307           0 :                 track->cb_color_size_idx[i] = 0;
     308           0 :                 track->cb_color_info[i] = 0;
     309           0 :                 track->cb_color_view[i] = 0xFFFFFFFF;
     310           0 :                 track->cb_color_bo[i] = NULL;
     311           0 :                 track->cb_color_bo_offset[i] = 0xFFFFFFFF;
     312           0 :                 track->cb_color_bo_mc[i] = 0xFFFFFFFF;
     313           0 :                 track->cb_color_frag_bo[i] = NULL;
     314           0 :                 track->cb_color_frag_offset[i] = 0xFFFFFFFF;
     315           0 :                 track->cb_color_tile_bo[i] = NULL;
     316           0 :                 track->cb_color_tile_offset[i] = 0xFFFFFFFF;
     317           0 :                 track->cb_color_mask[i] = 0xFFFFFFFF;
     318             :         }
     319           0 :         track->is_resolve = false;
     320           0 :         track->nsamples = 16;
     321           0 :         track->log_nsamples = 4;
     322           0 :         track->cb_target_mask = 0xFFFFFFFF;
     323           0 :         track->cb_shader_mask = 0xFFFFFFFF;
     324           0 :         track->cb_dirty = true;
     325           0 :         track->db_bo = NULL;
     326           0 :         track->db_bo_mc = 0xFFFFFFFF;
     327             :         /* assume the biggest format and that htile is enabled */
     328           0 :         track->db_depth_info = 7 | (1 << 25);
     329           0 :         track->db_depth_view = 0xFFFFC000;
     330           0 :         track->db_depth_size = 0xFFFFFFFF;
     331           0 :         track->db_depth_size_idx = 0;
     332           0 :         track->db_depth_control = 0xFFFFFFFF;
     333           0 :         track->db_dirty = true;
     334           0 :         track->htile_bo = NULL;
     335           0 :         track->htile_offset = 0xFFFFFFFF;
     336           0 :         track->htile_surface = 0;
     337             : 
     338           0 :         for (i = 0; i < 4; i++) {
     339           0 :                 track->vgt_strmout_size[i] = 0;
     340           0 :                 track->vgt_strmout_bo[i] = NULL;
     341           0 :                 track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
     342           0 :                 track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
     343             :         }
     344           0 :         track->streamout_dirty = true;
     345           0 :         track->sx_misc_kill_all_prims = false;
     346           0 : }
     347             : 
     348           0 : static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
     349             : {
     350           0 :         struct r600_cs_track *track = p->track;
     351             :         u32 slice_tile_max, size, tmp;
     352           0 :         u32 height, height_align, pitch, pitch_align, depth_align;
     353           0 :         u64 base_offset, base_align;
     354           0 :         struct array_mode_checker array_check;
     355           0 :         volatile u32 *ib = p->ib.ptr;
     356             :         unsigned array_mode;
     357             :         u32 format;
     358             :         /* When resolve is used, the second colorbuffer has always 1 sample. */
     359           0 :         unsigned nsamples = track->is_resolve && i == 1 ? 1 : track->nsamples;
     360             : 
     361           0 :         size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i];
     362           0 :         format = G_0280A0_FORMAT(track->cb_color_info[i]);
     363           0 :         if (!r600_fmt_is_valid_color(format)) {
     364           0 :                 dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n",
     365             :                          __func__, __LINE__, format,
     366             :                         i, track->cb_color_info[i]);
     367           0 :                 return -EINVAL;
     368             :         }
     369             :         /* pitch in pixels */
     370           0 :         pitch = (G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1) * 8;
     371           0 :         slice_tile_max = G_028060_SLICE_TILE_MAX(track->cb_color_size[i]) + 1;
     372           0 :         slice_tile_max *= 64;
     373           0 :         height = slice_tile_max / pitch;
     374           0 :         if (height > 8192)
     375             :                 height = 8192;
     376           0 :         array_mode = G_0280A0_ARRAY_MODE(track->cb_color_info[i]);
     377             : 
     378           0 :         base_offset = track->cb_color_bo_mc[i] + track->cb_color_bo_offset[i];
     379           0 :         array_check.array_mode = array_mode;
     380           0 :         array_check.group_size = track->group_size;
     381           0 :         array_check.nbanks = track->nbanks;
     382           0 :         array_check.npipes = track->npipes;
     383           0 :         array_check.nsamples = nsamples;
     384           0 :         array_check.blocksize = r600_fmt_get_blocksize(format);
     385           0 :         if (r600_get_array_mode_alignment(&array_check,
     386             :                                           &pitch_align, &height_align, &depth_align, &base_align)) {
     387           0 :                 dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
     388             :                          G_0280A0_ARRAY_MODE(track->cb_color_info[i]), i,
     389             :                          track->cb_color_info[i]);
     390           0 :                 return -EINVAL;
     391             :         }
     392           0 :         switch (array_mode) {
     393             :         case V_0280A0_ARRAY_LINEAR_GENERAL:
     394             :                 break;
     395             :         case V_0280A0_ARRAY_LINEAR_ALIGNED:
     396             :                 break;
     397             :         case V_0280A0_ARRAY_1D_TILED_THIN1:
     398             :                 /* avoid breaking userspace */
     399           0 :                 if (height > 7)
     400           0 :                         height &= ~0x7;
     401             :                 break;
     402             :         case V_0280A0_ARRAY_2D_TILED_THIN1:
     403             :                 break;
     404             :         default:
     405           0 :                 dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
     406             :                         G_0280A0_ARRAY_MODE(track->cb_color_info[i]), i,
     407             :                         track->cb_color_info[i]);
     408           0 :                 return -EINVAL;
     409             :         }
     410             : 
     411           0 :         if (!IS_ALIGNED(pitch, pitch_align)) {
     412           0 :                 dev_warn(p->dev, "%s:%d cb pitch (%d, 0x%x, %d) invalid\n",
     413             :                          __func__, __LINE__, pitch, pitch_align, array_mode);
     414           0 :                 return -EINVAL;
     415             :         }
     416           0 :         if (!IS_ALIGNED(height, height_align)) {
     417           0 :                 dev_warn(p->dev, "%s:%d cb height (%d, 0x%x, %d) invalid\n",
     418             :                          __func__, __LINE__, height, height_align, array_mode);
     419           0 :                 return -EINVAL;
     420             :         }
     421           0 :         if (!IS_ALIGNED(base_offset, base_align)) {
     422           0 :                 dev_warn(p->dev, "%s offset[%d] 0x%llx 0x%llx, %d not aligned\n", __func__, i,
     423             :                          base_offset, base_align, array_mode);
     424           0 :                 return -EINVAL;
     425             :         }
     426             : 
     427             :         /* check offset */
     428           0 :         tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) *
     429           0 :               r600_fmt_get_blocksize(format) * nsamples;
     430           0 :         switch (array_mode) {
     431             :         default:
     432             :         case V_0280A0_ARRAY_LINEAR_GENERAL:
     433             :         case V_0280A0_ARRAY_LINEAR_ALIGNED:
     434           0 :                 tmp += track->cb_color_view[i] & 0xFF;
     435           0 :                 break;
     436             :         case V_0280A0_ARRAY_1D_TILED_THIN1:
     437             :         case V_0280A0_ARRAY_2D_TILED_THIN1:
     438           0 :                 tmp += G_028080_SLICE_MAX(track->cb_color_view[i]) * tmp;
     439           0 :                 break;
     440             :         }
     441           0 :         if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
     442           0 :                 if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) {
     443             :                         /* the initial DDX does bad things with the CB size occasionally */
     444             :                         /* it rounds up height too far for slice tile max but the BO is smaller */
     445             :                         /* r600c,g also seem to flush at bad times in some apps resulting in
     446             :                          * bogus values here. So for linear just allow anything to avoid breaking
     447             :                          * broken userspace.
     448             :                          */
     449             :                 } else {
     450           0 :                         dev_warn(p->dev, "%s offset[%d] %d %llu %d %lu too big (%d %d) (%d %d %d)\n",
     451             :                                  __func__, i, array_mode,
     452             :                                  track->cb_color_bo_offset[i], tmp,
     453             :                                  radeon_bo_size(track->cb_color_bo[i]),
     454             :                                  pitch, height, r600_fmt_get_nblocksx(format, pitch),
     455             :                                  r600_fmt_get_nblocksy(format, height),
     456             :                                  r600_fmt_get_blocksize(format));
     457           0 :                         return -EINVAL;
     458             :                 }
     459             :         }
     460             :         /* limit max tile */
     461           0 :         tmp = (height * pitch) >> 6;
     462           0 :         if (tmp < slice_tile_max)
     463           0 :                 slice_tile_max = tmp;
     464           0 :         tmp = S_028060_PITCH_TILE_MAX((pitch / 8) - 1) |
     465           0 :                 S_028060_SLICE_TILE_MAX(slice_tile_max - 1);
     466           0 :         ib[track->cb_color_size_idx[i]] = tmp;
     467             : 
     468             :         /* FMASK/CMASK */
     469           0 :         switch (G_0280A0_TILE_MODE(track->cb_color_info[i])) {
     470             :         case V_0280A0_TILE_DISABLE:
     471             :                 break;
     472             :         case V_0280A0_FRAG_ENABLE:
     473           0 :                 if (track->nsamples > 1) {
     474           0 :                         uint32_t tile_max = G_028100_FMASK_TILE_MAX(track->cb_color_mask[i]);
     475             :                         /* the tile size is 8x8, but the size is in units of bits.
     476             :                          * for bytes, do just * 8. */
     477           0 :                         uint32_t bytes = track->nsamples * track->log_nsamples * 8 * (tile_max + 1);
     478             : 
     479           0 :                         if (bytes + track->cb_color_frag_offset[i] >
     480           0 :                             radeon_bo_size(track->cb_color_frag_bo[i])) {
     481           0 :                                 dev_warn(p->dev, "%s FMASK_TILE_MAX too large "
     482             :                                          "(tile_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n",
     483             :                                          __func__, tile_max, bytes,
     484             :                                          track->cb_color_frag_offset[i],
     485             :                                          radeon_bo_size(track->cb_color_frag_bo[i]));
     486           0 :                                 return -EINVAL;
     487             :                         }
     488           0 :                 }
     489             :                 /* fall through */
     490             :         case V_0280A0_CLEAR_ENABLE:
     491             :         {
     492           0 :                 uint32_t block_max = G_028100_CMASK_BLOCK_MAX(track->cb_color_mask[i]);
     493             :                 /* One block = 128x128 pixels, one 8x8 tile has 4 bits..
     494             :                  * (128*128) / (8*8) / 2 = 128 bytes per block. */
     495           0 :                 uint32_t bytes = (block_max + 1) * 128;
     496             : 
     497           0 :                 if (bytes + track->cb_color_tile_offset[i] >
     498           0 :                     radeon_bo_size(track->cb_color_tile_bo[i])) {
     499           0 :                         dev_warn(p->dev, "%s CMASK_BLOCK_MAX too large "
     500             :                                  "(block_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n",
     501             :                                  __func__, block_max, bytes,
     502             :                                  track->cb_color_tile_offset[i],
     503             :                                  radeon_bo_size(track->cb_color_tile_bo[i]));
     504           0 :                         return -EINVAL;
     505             :                 }
     506           0 :                 break;
     507             :         }
     508             :         default:
     509           0 :                 dev_warn(p->dev, "%s invalid tile mode\n", __func__);
     510           0 :                 return -EINVAL;
     511             :         }
     512           0 :         return 0;
     513           0 : }
     514             : 
     515           0 : static int r600_cs_track_validate_db(struct radeon_cs_parser *p)
     516             : {
     517           0 :         struct r600_cs_track *track = p->track;
     518             :         u32 nviews, bpe, ntiles, size, slice_tile_max, tmp;
     519           0 :         u32 height_align, pitch_align, depth_align;
     520             :         u32 pitch = 8192;
     521             :         u32 height = 8192;
     522           0 :         u64 base_offset, base_align;
     523           0 :         struct array_mode_checker array_check;
     524             :         int array_mode;
     525           0 :         volatile u32 *ib = p->ib.ptr;
     526             : 
     527             : 
     528           0 :         if (track->db_bo == NULL) {
     529           0 :                 dev_warn(p->dev, "z/stencil with no depth buffer\n");
     530           0 :                 return -EINVAL;
     531             :         }
     532           0 :         switch (G_028010_FORMAT(track->db_depth_info)) {
     533             :         case V_028010_DEPTH_16:
     534             :                 bpe = 2;
     535           0 :                 break;
     536             :         case V_028010_DEPTH_X8_24:
     537             :         case V_028010_DEPTH_8_24:
     538             :         case V_028010_DEPTH_X8_24_FLOAT:
     539             :         case V_028010_DEPTH_8_24_FLOAT:
     540             :         case V_028010_DEPTH_32_FLOAT:
     541             :                 bpe = 4;
     542           0 :                 break;
     543             :         case V_028010_DEPTH_X24_8_32_FLOAT:
     544             :                 bpe = 8;
     545           0 :                 break;
     546             :         default:
     547           0 :                 dev_warn(p->dev, "z/stencil with invalid format %d\n", G_028010_FORMAT(track->db_depth_info));
     548           0 :                 return -EINVAL;
     549             :         }
     550           0 :         if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
     551           0 :                 if (!track->db_depth_size_idx) {
     552           0 :                         dev_warn(p->dev, "z/stencil buffer size not set\n");
     553           0 :                         return -EINVAL;
     554             :                 }
     555           0 :                 tmp = radeon_bo_size(track->db_bo) - track->db_offset;
     556           0 :                 tmp = (tmp / bpe) >> 6;
     557           0 :                 if (!tmp) {
     558           0 :                         dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %ld)\n",
     559             :                                         track->db_depth_size, bpe, track->db_offset,
     560             :                                         radeon_bo_size(track->db_bo));
     561           0 :                         return -EINVAL;
     562             :                 }
     563           0 :                 ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF);
     564           0 :         } else {
     565           0 :                 size = radeon_bo_size(track->db_bo);
     566             :                 /* pitch in pixels */
     567           0 :                 pitch = (G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1) * 8;
     568           0 :                 slice_tile_max = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
     569           0 :                 slice_tile_max *= 64;
     570           0 :                 height = slice_tile_max / pitch;
     571           0 :                 if (height > 8192)
     572             :                         height = 8192;
     573           0 :                 base_offset = track->db_bo_mc + track->db_offset;
     574           0 :                 array_mode = G_028010_ARRAY_MODE(track->db_depth_info);
     575           0 :                 array_check.array_mode = array_mode;
     576           0 :                 array_check.group_size = track->group_size;
     577           0 :                 array_check.nbanks = track->nbanks;
     578           0 :                 array_check.npipes = track->npipes;
     579           0 :                 array_check.nsamples = track->nsamples;
     580           0 :                 array_check.blocksize = bpe;
     581           0 :                 if (r600_get_array_mode_alignment(&array_check,
     582             :                                         &pitch_align, &height_align, &depth_align, &base_align)) {
     583           0 :                         dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
     584             :                                         G_028010_ARRAY_MODE(track->db_depth_info),
     585             :                                         track->db_depth_info);
     586           0 :                         return -EINVAL;
     587             :                 }
     588           0 :                 switch (array_mode) {
     589             :                 case V_028010_ARRAY_1D_TILED_THIN1:
     590             :                         /* don't break userspace */
     591           0 :                         height &= ~0x7;
     592           0 :                         break;
     593             :                 case V_028010_ARRAY_2D_TILED_THIN1:
     594             :                         break;
     595             :                 default:
     596           0 :                         dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
     597             :                                         G_028010_ARRAY_MODE(track->db_depth_info),
     598             :                                         track->db_depth_info);
     599           0 :                         return -EINVAL;
     600             :                 }
     601             : 
     602           0 :                 if (!IS_ALIGNED(pitch, pitch_align)) {
     603           0 :                         dev_warn(p->dev, "%s:%d db pitch (%d, 0x%x, %d) invalid\n",
     604             :                                         __func__, __LINE__, pitch, pitch_align, array_mode);
     605           0 :                         return -EINVAL;
     606             :                 }
     607           0 :                 if (!IS_ALIGNED(height, height_align)) {
     608           0 :                         dev_warn(p->dev, "%s:%d db height (%d, 0x%x, %d) invalid\n",
     609             :                                         __func__, __LINE__, height, height_align, array_mode);
     610           0 :                         return -EINVAL;
     611             :                 }
     612           0 :                 if (!IS_ALIGNED(base_offset, base_align)) {
     613           0 :                         dev_warn(p->dev, "%s offset 0x%llx, 0x%llx, %d not aligned\n", __func__,
     614             :                                         base_offset, base_align, array_mode);
     615           0 :                         return -EINVAL;
     616             :                 }
     617             : 
     618           0 :                 ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
     619           0 :                 nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
     620           0 :                 tmp = ntiles * bpe * 64 * nviews * track->nsamples;
     621           0 :                 if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
     622           0 :                         dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n",
     623             :                                         array_mode,
     624             :                                         track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
     625             :                                         radeon_bo_size(track->db_bo));
     626           0 :                         return -EINVAL;
     627             :                 }
     628             :         }
     629             : 
     630             :         /* hyperz */
     631           0 :         if (G_028010_TILE_SURFACE_ENABLE(track->db_depth_info)) {
     632             :                 unsigned long size;
     633             :                 unsigned nbx, nby;
     634             : 
     635           0 :                 if (track->htile_bo == NULL) {
     636           0 :                         dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n",
     637             :                                  __func__, __LINE__, track->db_depth_info);
     638           0 :                         return -EINVAL;
     639             :                 }
     640           0 :                 if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
     641           0 :                         dev_warn(p->dev, "%s:%d htile can't be enabled with bogus db_depth_size 0x%08x\n",
     642             :                                  __func__, __LINE__, track->db_depth_size);
     643           0 :                         return -EINVAL;
     644             :                 }
     645             : 
     646             :                 nbx = pitch;
     647             :                 nby = height;
     648           0 :                 if (G_028D24_LINEAR(track->htile_surface)) {
     649             :                         /* nbx must be 16 htiles aligned == 16 * 8 pixel aligned */
     650           0 :                         nbx = round_up(nbx, 16 * 8);
     651             :                         /* nby is npipes htiles aligned == npipes * 8 pixel aligned */
     652           0 :                         nby = round_up(nby, track->npipes * 8);
     653           0 :                 } else {
     654             :                         /* always assume 8x8 htile */
     655             :                         /* align is htile align * 8, htile align vary according to
     656             :                          * number of pipe and tile width and nby
     657             :                          */
     658           0 :                         switch (track->npipes) {
     659             :                         case 8:
     660             :                                 /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
     661           0 :                                 nbx = round_up(nbx, 64 * 8);
     662           0 :                                 nby = round_up(nby, 64 * 8);
     663           0 :                                 break;
     664             :                         case 4:
     665             :                                 /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
     666           0 :                                 nbx = round_up(nbx, 64 * 8);
     667           0 :                                 nby = round_up(nby, 32 * 8);
     668           0 :                                 break;
     669             :                         case 2:
     670             :                                 /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
     671           0 :                                 nbx = round_up(nbx, 32 * 8);
     672           0 :                                 nby = round_up(nby, 32 * 8);
     673           0 :                                 break;
     674             :                         case 1:
     675             :                                 /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
     676           0 :                                 nbx = round_up(nbx, 32 * 8);
     677           0 :                                 nby = round_up(nby, 16 * 8);
     678           0 :                                 break;
     679             :                         default:
     680           0 :                                 dev_warn(p->dev, "%s:%d invalid num pipes %d\n",
     681             :                                          __func__, __LINE__, track->npipes);
     682           0 :                                 return -EINVAL;
     683             :                         }
     684             :                 }
     685             :                 /* compute number of htile */
     686           0 :                 nbx = nbx >> 3;
     687           0 :                 nby = nby >> 3;
     688             :                 /* size must be aligned on npipes * 2K boundary */
     689           0 :                 size = roundup(nbx * nby * 4, track->npipes * (2 << 10));
     690           0 :                 size += track->htile_offset;
     691             : 
     692           0 :                 if (size > radeon_bo_size(track->htile_bo)) {
     693           0 :                         dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n",
     694             :                                  __func__, __LINE__, radeon_bo_size(track->htile_bo),
     695             :                                  size, nbx, nby);
     696           0 :                         return -EINVAL;
     697             :                 }
     698           0 :         }
     699             : 
     700           0 :         track->db_dirty = false;
     701           0 :         return 0;
     702           0 : }
     703             : 
     704           0 : static int r600_cs_track_check(struct radeon_cs_parser *p)
     705             : {
     706           0 :         struct r600_cs_track *track = p->track;
     707             :         u32 tmp;
     708             :         int r, i;
     709             : 
     710             :         /* on legacy kernel we don't perform advanced check */
     711           0 :         if (p->rdev == NULL)
     712           0 :                 return 0;
     713             : 
     714             :         /* check streamout */
     715           0 :         if (track->streamout_dirty && track->vgt_strmout_en) {
     716           0 :                 for (i = 0; i < 4; i++) {
     717           0 :                         if (track->vgt_strmout_buffer_en & (1 << i)) {
     718           0 :                                 if (track->vgt_strmout_bo[i]) {
     719           0 :                                         u64 offset = (u64)track->vgt_strmout_bo_offset[i] +
     720           0 :                                                 (u64)track->vgt_strmout_size[i];
     721           0 :                                         if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) {
     722           0 :                                                 DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n",
     723             :                                                           i, offset,
     724             :                                                           radeon_bo_size(track->vgt_strmout_bo[i]));
     725           0 :                                                 return -EINVAL;
     726             :                                         }
     727           0 :                                 } else {
     728           0 :                                         dev_warn(p->dev, "No buffer for streamout %d\n", i);
     729           0 :                                         return -EINVAL;
     730             :                                 }
     731             :                         }
     732             :                 }
     733           0 :                 track->streamout_dirty = false;
     734           0 :         }
     735             : 
     736           0 :         if (track->sx_misc_kill_all_prims)
     737           0 :                 return 0;
     738             : 
     739             :         /* check that we have a cb for each enabled target, we don't check
     740             :          * shader_mask because it seems mesa isn't always setting it :(
     741             :          */
     742           0 :         if (track->cb_dirty) {
     743           0 :                 tmp = track->cb_target_mask;
     744             : 
     745             :                 /* We must check both colorbuffers for RESOLVE. */
     746           0 :                 if (track->is_resolve) {
     747           0 :                         tmp |= 0xff;
     748           0 :                 }
     749             : 
     750           0 :                 for (i = 0; i < 8; i++) {
     751           0 :                         u32 format = G_0280A0_FORMAT(track->cb_color_info[i]);
     752             : 
     753           0 :                         if (format != V_0280A0_COLOR_INVALID &&
     754           0 :                             (tmp >> (i * 4)) & 0xF) {
     755             :                                 /* at least one component is enabled */
     756           0 :                                 if (track->cb_color_bo[i] == NULL) {
     757           0 :                                         dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n",
     758             :                                                 __func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i);
     759           0 :                                         return -EINVAL;
     760             :                                 }
     761             :                                 /* perform rewrite of CB_COLOR[0-7]_SIZE */
     762           0 :                                 r = r600_cs_track_validate_cb(p, i);
     763           0 :                                 if (r)
     764           0 :                                         return r;
     765             :                         }
     766           0 :                 }
     767           0 :                 track->cb_dirty = false;
     768           0 :         }
     769             : 
     770             :         /* Check depth buffer */
     771           0 :         if (track->db_dirty &&
     772           0 :             G_028010_FORMAT(track->db_depth_info) != V_028010_DEPTH_INVALID &&
     773           0 :             (G_028800_STENCIL_ENABLE(track->db_depth_control) ||
     774           0 :              G_028800_Z_ENABLE(track->db_depth_control))) {
     775           0 :                 r = r600_cs_track_validate_db(p);
     776           0 :                 if (r)
     777           0 :                         return r;
     778             :         }
     779             : 
     780           0 :         return 0;
     781           0 : }
     782             : 
     783             : /**
     784             :  * r600_cs_packet_parse_vline() - parse userspace VLINE packet
     785             :  * @parser:             parser structure holding parsing context.
     786             :  *
     787             :  * This is an R600-specific function for parsing VLINE packets.
     788             :  * Real work is done by r600_cs_common_vline_parse function.
     789             :  * Here we just set up ASIC-specific register table and call
     790             :  * the common implementation function.
     791             :  */
     792           0 : static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
     793             : {
     794             :         static uint32_t vline_start_end[2] = {AVIVO_D1MODE_VLINE_START_END,
     795             :                                               AVIVO_D2MODE_VLINE_START_END};
     796             :         static uint32_t vline_status[2] = {AVIVO_D1MODE_VLINE_STATUS,
     797             :                                            AVIVO_D2MODE_VLINE_STATUS};
     798             : 
     799           0 :         return r600_cs_common_vline_parse(p, vline_start_end, vline_status);
     800             : }
     801             : 
     802             : /**
     803             :  * r600_cs_common_vline_parse() - common vline parser
     804             :  * @parser:             parser structure holding parsing context.
     805             :  * @vline_start_end:    table of vline_start_end registers
     806             :  * @vline_status:       table of vline_status registers
     807             :  *
     808             :  * Userspace sends a special sequence for VLINE waits.
     809             :  * PACKET0 - VLINE_START_END + value
     810             :  * PACKET3 - WAIT_REG_MEM poll vline status reg
     811             :  * RELOC (P3) - crtc_id in reloc.
     812             :  *
     813             :  * This function parses this and relocates the VLINE START END
     814             :  * and WAIT_REG_MEM packets to the correct crtc.
     815             :  * It also detects a switched off crtc and nulls out the
     816             :  * wait in that case. This function is common for all ASICs that
     817             :  * are R600 and newer. The parsing algorithm is the same, and only
     818             :  * differs in which registers are used.
     819             :  *
     820             :  * Caller is the ASIC-specific function which passes the parser
     821             :  * context and ASIC-specific register table
     822             :  */
     823           0 : int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
     824             :                                uint32_t *vline_start_end,
     825             :                                uint32_t *vline_status)
     826             : {
     827             :         struct drm_crtc *crtc;
     828             :         struct radeon_crtc *radeon_crtc;
     829           0 :         struct radeon_cs_packet p3reloc, wait_reg_mem;
     830             :         int crtc_id;
     831             :         int r;
     832             :         uint32_t header, h_idx, reg, wait_reg_mem_info;
     833             :         volatile uint32_t *ib;
     834             : 
     835           0 :         ib = p->ib.ptr;
     836             : 
     837             :         /* parse the WAIT_REG_MEM */
     838           0 :         r = radeon_cs_packet_parse(p, &wait_reg_mem, p->idx);
     839           0 :         if (r)
     840           0 :                 return r;
     841             : 
     842             :         /* check its a WAIT_REG_MEM */
     843           0 :         if (wait_reg_mem.type != RADEON_PACKET_TYPE3 ||
     844           0 :             wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
     845           0 :                 DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
     846           0 :                 return -EINVAL;
     847             :         }
     848             : 
     849           0 :         wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
     850             :         /* bit 4 is reg (0) or mem (1) */
     851           0 :         if (wait_reg_mem_info & 0x10) {
     852           0 :                 DRM_ERROR("vline WAIT_REG_MEM waiting on MEM instead of REG\n");
     853           0 :                 return -EINVAL;
     854             :         }
     855             :         /* bit 8 is me (0) or pfp (1) */
     856           0 :         if (wait_reg_mem_info & 0x100) {
     857           0 :                 DRM_ERROR("vline WAIT_REG_MEM waiting on PFP instead of ME\n");
     858           0 :                 return -EINVAL;
     859             :         }
     860             :         /* waiting for value to be equal */
     861           0 :         if ((wait_reg_mem_info & 0x7) != 0x3) {
     862           0 :                 DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
     863           0 :                 return -EINVAL;
     864             :         }
     865           0 :         if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != vline_status[0]) {
     866           0 :                 DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
     867           0 :                 return -EINVAL;
     868             :         }
     869             : 
     870           0 :         if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != RADEON_VLINE_STAT) {
     871           0 :                 DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
     872           0 :                 return -EINVAL;
     873             :         }
     874             : 
     875             :         /* jump over the NOP */
     876           0 :         r = radeon_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
     877           0 :         if (r)
     878           0 :                 return r;
     879             : 
     880           0 :         h_idx = p->idx - 2;
     881           0 :         p->idx += wait_reg_mem.count + 2;
     882           0 :         p->idx += p3reloc.count + 2;
     883             : 
     884           0 :         header = radeon_get_ib_value(p, h_idx);
     885           0 :         crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
     886           0 :         reg = R600_CP_PACKET0_GET_REG(header);
     887             : 
     888           0 :         crtc = drm_crtc_find(p->rdev->ddev, crtc_id);
     889           0 :         if (!crtc) {
     890           0 :                 DRM_ERROR("cannot find crtc %d\n", crtc_id);
     891           0 :                 return -ENOENT;
     892             :         }
     893           0 :         radeon_crtc = to_radeon_crtc(crtc);
     894           0 :         crtc_id = radeon_crtc->crtc_id;
     895             : 
     896           0 :         if (!crtc->enabled) {
     897             :                 /* CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
     898           0 :                 ib[h_idx + 2] = PACKET2(0);
     899           0 :                 ib[h_idx + 3] = PACKET2(0);
     900           0 :                 ib[h_idx + 4] = PACKET2(0);
     901           0 :                 ib[h_idx + 5] = PACKET2(0);
     902           0 :                 ib[h_idx + 6] = PACKET2(0);
     903           0 :                 ib[h_idx + 7] = PACKET2(0);
     904           0 :                 ib[h_idx + 8] = PACKET2(0);
     905           0 :         } else if (reg == vline_start_end[0]) {
     906           0 :                 header &= ~R600_CP_PACKET0_REG_MASK;
     907           0 :                 header |= vline_start_end[crtc_id] >> 2;
     908           0 :                 ib[h_idx] = header;
     909           0 :                 ib[h_idx + 4] = vline_status[crtc_id] >> 2;
     910             :         } else {
     911           0 :                 DRM_ERROR("unknown crtc reloc\n");
     912           0 :                 return -EINVAL;
     913             :         }
     914           0 :         return 0;
     915           0 : }
     916             : 
     917           0 : static int r600_packet0_check(struct radeon_cs_parser *p,
     918             :                                 struct radeon_cs_packet *pkt,
     919             :                                 unsigned idx, unsigned reg)
     920             : {
     921             :         int r;
     922             : 
     923           0 :         switch (reg) {
     924             :         case AVIVO_D1MODE_VLINE_START_END:
     925           0 :                 r = r600_cs_packet_parse_vline(p);
     926           0 :                 if (r) {
     927           0 :                         DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
     928             :                                         idx, reg);
     929           0 :                         return r;
     930             :                 }
     931             :                 break;
     932             :         default:
     933           0 :                 printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
     934             :                        reg, idx);
     935           0 :                 return -EINVAL;
     936             :         }
     937           0 :         return 0;
     938           0 : }
     939             : 
     940           0 : static int r600_cs_parse_packet0(struct radeon_cs_parser *p,
     941             :                                 struct radeon_cs_packet *pkt)
     942             : {
     943             :         unsigned reg, i;
     944             :         unsigned idx;
     945             :         int r;
     946             : 
     947           0 :         idx = pkt->idx + 1;
     948           0 :         reg = pkt->reg;
     949           0 :         for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
     950           0 :                 r = r600_packet0_check(p, pkt, idx, reg);
     951           0 :                 if (r) {
     952           0 :                         return r;
     953             :                 }
     954             :         }
     955           0 :         return 0;
     956           0 : }
     957             : 
     958             : /**
     959             :  * r600_cs_check_reg() - check if register is authorized or not
     960             :  * @parser: parser structure holding parsing context
     961             :  * @reg: register we are testing
     962             :  * @idx: index into the cs buffer
     963             :  *
     964             :  * This function will test against r600_reg_safe_bm and return 0
     965             :  * if register is safe. If register is not flag as safe this function
     966             :  * will test it against a list of register needind special handling.
     967             :  */
     968           0 : static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
     969             : {
     970           0 :         struct r600_cs_track *track = (struct r600_cs_track *)p->track;
     971           0 :         struct radeon_bo_list *reloc;
     972             :         u32 m, i, tmp, *ib;
     973             :         int r;
     974             : 
     975           0 :         i = (reg >> 7);
     976           0 :         if (i >= ARRAY_SIZE(r600_reg_safe_bm)) {
     977           0 :                 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
     978           0 :                 return -EINVAL;
     979             :         }
     980           0 :         m = 1 << ((reg >> 2) & 31);
     981           0 :         if (!(r600_reg_safe_bm[i] & m))
     982           0 :                 return 0;
     983           0 :         ib = p->ib.ptr;
     984           0 :         switch (reg) {
     985             :         /* force following reg to 0 in an attempt to disable out buffer
     986             :          * which will need us to better understand how it works to perform
     987             :          * security check on it (Jerome)
     988             :          */
     989             :         case R_0288A8_SQ_ESGS_RING_ITEMSIZE:
     990             :         case R_008C44_SQ_ESGS_RING_SIZE:
     991             :         case R_0288B0_SQ_ESTMP_RING_ITEMSIZE:
     992             :         case R_008C54_SQ_ESTMP_RING_SIZE:
     993             :         case R_0288C0_SQ_FBUF_RING_ITEMSIZE:
     994             :         case R_008C74_SQ_FBUF_RING_SIZE:
     995             :         case R_0288B4_SQ_GSTMP_RING_ITEMSIZE:
     996             :         case R_008C5C_SQ_GSTMP_RING_SIZE:
     997             :         case R_0288AC_SQ_GSVS_RING_ITEMSIZE:
     998             :         case R_008C4C_SQ_GSVS_RING_SIZE:
     999             :         case R_0288BC_SQ_PSTMP_RING_ITEMSIZE:
    1000             :         case R_008C6C_SQ_PSTMP_RING_SIZE:
    1001             :         case R_0288C4_SQ_REDUC_RING_ITEMSIZE:
    1002             :         case R_008C7C_SQ_REDUC_RING_SIZE:
    1003             :         case R_0288B8_SQ_VSTMP_RING_ITEMSIZE:
    1004             :         case R_008C64_SQ_VSTMP_RING_SIZE:
    1005             :         case R_0288C8_SQ_GS_VERT_ITEMSIZE:
    1006             :                 /* get value to populate the IB don't remove */
    1007             :                 /*tmp =radeon_get_ib_value(p, idx);
    1008             :                   ib[idx] = 0;*/
    1009             :                 break;
    1010             :         case SQ_ESGS_RING_BASE:
    1011             :         case SQ_GSVS_RING_BASE:
    1012             :         case SQ_ESTMP_RING_BASE:
    1013             :         case SQ_GSTMP_RING_BASE:
    1014             :         case SQ_PSTMP_RING_BASE:
    1015             :         case SQ_VSTMP_RING_BASE:
    1016           0 :                 r = radeon_cs_packet_next_reloc(p, &reloc, 0);
    1017           0 :                 if (r) {
    1018           0 :                         dev_warn(p->dev, "bad SET_CONTEXT_REG "
    1019             :                                         "0x%04X\n", reg);
    1020           0 :                         return -EINVAL;
    1021             :                 }
    1022           0 :                 ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
    1023           0 :                 break;
    1024             :         case SQ_CONFIG:
    1025           0 :                 track->sq_config = radeon_get_ib_value(p, idx);
    1026           0 :                 break;
    1027             :         case R_028800_DB_DEPTH_CONTROL:
    1028           0 :                 track->db_depth_control = radeon_get_ib_value(p, idx);
    1029           0 :                 track->db_dirty = true;
    1030           0 :                 break;
    1031             :         case R_028010_DB_DEPTH_INFO:
    1032           0 :                 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) &&
    1033           0 :                     radeon_cs_packet_next_is_pkt3_nop(p)) {
    1034           0 :                         r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1035           0 :                         if (r) {
    1036           0 :                                 dev_warn(p->dev, "bad SET_CONTEXT_REG "
    1037             :                                          "0x%04X\n", reg);
    1038           0 :                                 return -EINVAL;
    1039             :                         }
    1040           0 :                         track->db_depth_info = radeon_get_ib_value(p, idx);
    1041           0 :                         ib[idx] &= C_028010_ARRAY_MODE;
    1042           0 :                         track->db_depth_info &= C_028010_ARRAY_MODE;
    1043           0 :                         if (reloc->tiling_flags & RADEON_TILING_MACRO) {
    1044           0 :                                 ib[idx] |= S_028010_ARRAY_MODE(V_028010_ARRAY_2D_TILED_THIN1);
    1045           0 :                                 track->db_depth_info |= S_028010_ARRAY_MODE(V_028010_ARRAY_2D_TILED_THIN1);
    1046           0 :                         } else {
    1047           0 :                                 ib[idx] |= S_028010_ARRAY_MODE(V_028010_ARRAY_1D_TILED_THIN1);
    1048           0 :                                 track->db_depth_info |= S_028010_ARRAY_MODE(V_028010_ARRAY_1D_TILED_THIN1);
    1049             :                         }
    1050             :                 } else {
    1051           0 :                         track->db_depth_info = radeon_get_ib_value(p, idx);
    1052             :                 }
    1053           0 :                 track->db_dirty = true;
    1054           0 :                 break;
    1055             :         case R_028004_DB_DEPTH_VIEW:
    1056           0 :                 track->db_depth_view = radeon_get_ib_value(p, idx);
    1057           0 :                 track->db_dirty = true;
    1058           0 :                 break;
    1059             :         case R_028000_DB_DEPTH_SIZE:
    1060           0 :                 track->db_depth_size = radeon_get_ib_value(p, idx);
    1061           0 :                 track->db_depth_size_idx = idx;
    1062           0 :                 track->db_dirty = true;
    1063           0 :                 break;
    1064             :         case R_028AB0_VGT_STRMOUT_EN:
    1065           0 :                 track->vgt_strmout_en = radeon_get_ib_value(p, idx);
    1066           0 :                 track->streamout_dirty = true;
    1067           0 :                 break;
    1068             :         case R_028B20_VGT_STRMOUT_BUFFER_EN:
    1069           0 :                 track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx);
    1070           0 :                 track->streamout_dirty = true;
    1071           0 :                 break;
    1072             :         case VGT_STRMOUT_BUFFER_BASE_0:
    1073             :         case VGT_STRMOUT_BUFFER_BASE_1:
    1074             :         case VGT_STRMOUT_BUFFER_BASE_2:
    1075             :         case VGT_STRMOUT_BUFFER_BASE_3:
    1076           0 :                 r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1077           0 :                 if (r) {
    1078           0 :                         dev_warn(p->dev, "bad SET_CONTEXT_REG "
    1079             :                                         "0x%04X\n", reg);
    1080           0 :                         return -EINVAL;
    1081             :                 }
    1082           0 :                 tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
    1083           0 :                 track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
    1084           0 :                 ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
    1085           0 :                 track->vgt_strmout_bo[tmp] = reloc->robj;
    1086           0 :                 track->vgt_strmout_bo_mc[tmp] = reloc->gpu_offset;
    1087           0 :                 track->streamout_dirty = true;
    1088           0 :                 break;
    1089             :         case VGT_STRMOUT_BUFFER_SIZE_0:
    1090             :         case VGT_STRMOUT_BUFFER_SIZE_1:
    1091             :         case VGT_STRMOUT_BUFFER_SIZE_2:
    1092             :         case VGT_STRMOUT_BUFFER_SIZE_3:
    1093           0 :                 tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
    1094             :                 /* size in register is DWs, convert to bytes */
    1095           0 :                 track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4;
    1096           0 :                 track->streamout_dirty = true;
    1097           0 :                 break;
    1098             :         case CP_COHER_BASE:
    1099           0 :                 r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1100           0 :                 if (r) {
    1101           0 :                         dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
    1102             :                                         "0x%04X\n", reg);
    1103           0 :                         return -EINVAL;
    1104             :                 }
    1105           0 :                 ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
    1106           0 :                 break;
    1107             :         case R_028238_CB_TARGET_MASK:
    1108           0 :                 track->cb_target_mask = radeon_get_ib_value(p, idx);
    1109           0 :                 track->cb_dirty = true;
    1110           0 :                 break;
    1111             :         case R_02823C_CB_SHADER_MASK:
    1112           0 :                 track->cb_shader_mask = radeon_get_ib_value(p, idx);
    1113           0 :                 break;
    1114             :         case R_028C04_PA_SC_AA_CONFIG:
    1115           0 :                 tmp = G_028C04_MSAA_NUM_SAMPLES(radeon_get_ib_value(p, idx));
    1116           0 :                 track->log_nsamples = tmp;
    1117           0 :                 track->nsamples = 1 << tmp;
    1118           0 :                 track->cb_dirty = true;
    1119           0 :                 break;
    1120             :         case R_028808_CB_COLOR_CONTROL:
    1121           0 :                 tmp = G_028808_SPECIAL_OP(radeon_get_ib_value(p, idx));
    1122           0 :                 track->is_resolve = tmp == V_028808_SPECIAL_RESOLVE_BOX;
    1123           0 :                 track->cb_dirty = true;
    1124           0 :                 break;
    1125             :         case R_0280A0_CB_COLOR0_INFO:
    1126             :         case R_0280A4_CB_COLOR1_INFO:
    1127             :         case R_0280A8_CB_COLOR2_INFO:
    1128             :         case R_0280AC_CB_COLOR3_INFO:
    1129             :         case R_0280B0_CB_COLOR4_INFO:
    1130             :         case R_0280B4_CB_COLOR5_INFO:
    1131             :         case R_0280B8_CB_COLOR6_INFO:
    1132             :         case R_0280BC_CB_COLOR7_INFO:
    1133           0 :                 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) &&
    1134           0 :                      radeon_cs_packet_next_is_pkt3_nop(p)) {
    1135           0 :                         r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1136           0 :                         if (r) {
    1137           0 :                                 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
    1138           0 :                                 return -EINVAL;
    1139             :                         }
    1140           0 :                         tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4;
    1141           0 :                         track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
    1142           0 :                         if (reloc->tiling_flags & RADEON_TILING_MACRO) {
    1143           0 :                                 ib[idx] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_2D_TILED_THIN1);
    1144           0 :                                 track->cb_color_info[tmp] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_2D_TILED_THIN1);
    1145           0 :                         } else if (reloc->tiling_flags & RADEON_TILING_MICRO) {
    1146           0 :                                 ib[idx] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_1D_TILED_THIN1);
    1147           0 :                                 track->cb_color_info[tmp] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_1D_TILED_THIN1);
    1148           0 :                         }
    1149             :                 } else {
    1150           0 :                         tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4;
    1151           0 :                         track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
    1152             :                 }
    1153           0 :                 track->cb_dirty = true;
    1154           0 :                 break;
    1155             :         case R_028080_CB_COLOR0_VIEW:
    1156             :         case R_028084_CB_COLOR1_VIEW:
    1157             :         case R_028088_CB_COLOR2_VIEW:
    1158             :         case R_02808C_CB_COLOR3_VIEW:
    1159             :         case R_028090_CB_COLOR4_VIEW:
    1160             :         case R_028094_CB_COLOR5_VIEW:
    1161             :         case R_028098_CB_COLOR6_VIEW:
    1162             :         case R_02809C_CB_COLOR7_VIEW:
    1163           0 :                 tmp = (reg - R_028080_CB_COLOR0_VIEW) / 4;
    1164           0 :                 track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
    1165           0 :                 track->cb_dirty = true;
    1166           0 :                 break;
    1167             :         case R_028060_CB_COLOR0_SIZE:
    1168             :         case R_028064_CB_COLOR1_SIZE:
    1169             :         case R_028068_CB_COLOR2_SIZE:
    1170             :         case R_02806C_CB_COLOR3_SIZE:
    1171             :         case R_028070_CB_COLOR4_SIZE:
    1172             :         case R_028074_CB_COLOR5_SIZE:
    1173             :         case R_028078_CB_COLOR6_SIZE:
    1174             :         case R_02807C_CB_COLOR7_SIZE:
    1175           0 :                 tmp = (reg - R_028060_CB_COLOR0_SIZE) / 4;
    1176           0 :                 track->cb_color_size[tmp] = radeon_get_ib_value(p, idx);
    1177           0 :                 track->cb_color_size_idx[tmp] = idx;
    1178           0 :                 track->cb_dirty = true;
    1179           0 :                 break;
    1180             :                 /* This register were added late, there is userspace
    1181             :                  * which does provide relocation for those but set
    1182             :                  * 0 offset. In order to avoid breaking old userspace
    1183             :                  * we detect this and set address to point to last
    1184             :                  * CB_COLOR0_BASE, note that if userspace doesn't set
    1185             :                  * CB_COLOR0_BASE before this register we will report
    1186             :                  * error. Old userspace always set CB_COLOR0_BASE
    1187             :                  * before any of this.
    1188             :                  */
    1189             :         case R_0280E0_CB_COLOR0_FRAG:
    1190             :         case R_0280E4_CB_COLOR1_FRAG:
    1191             :         case R_0280E8_CB_COLOR2_FRAG:
    1192             :         case R_0280EC_CB_COLOR3_FRAG:
    1193             :         case R_0280F0_CB_COLOR4_FRAG:
    1194             :         case R_0280F4_CB_COLOR5_FRAG:
    1195             :         case R_0280F8_CB_COLOR6_FRAG:
    1196             :         case R_0280FC_CB_COLOR7_FRAG:
    1197           0 :                 tmp = (reg - R_0280E0_CB_COLOR0_FRAG) / 4;
    1198           0 :                 if (!radeon_cs_packet_next_is_pkt3_nop(p)) {
    1199           0 :                         if (!track->cb_color_base_last[tmp]) {
    1200           0 :                                 dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
    1201           0 :                                 return -EINVAL;
    1202             :                         }
    1203           0 :                         track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp];
    1204           0 :                         track->cb_color_frag_offset[tmp] = track->cb_color_bo_offset[tmp];
    1205           0 :                         ib[idx] = track->cb_color_base_last[tmp];
    1206           0 :                 } else {
    1207           0 :                         r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1208           0 :                         if (r) {
    1209           0 :                                 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
    1210           0 :                                 return -EINVAL;
    1211             :                         }
    1212           0 :                         track->cb_color_frag_bo[tmp] = reloc->robj;
    1213           0 :                         track->cb_color_frag_offset[tmp] = (u64)ib[idx] << 8;
    1214           0 :                         ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
    1215             :                 }
    1216           0 :                 if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
    1217           0 :                         track->cb_dirty = true;
    1218           0 :                 }
    1219             :                 break;
    1220             :         case R_0280C0_CB_COLOR0_TILE:
    1221             :         case R_0280C4_CB_COLOR1_TILE:
    1222             :         case R_0280C8_CB_COLOR2_TILE:
    1223             :         case R_0280CC_CB_COLOR3_TILE:
    1224             :         case R_0280D0_CB_COLOR4_TILE:
    1225             :         case R_0280D4_CB_COLOR5_TILE:
    1226             :         case R_0280D8_CB_COLOR6_TILE:
    1227             :         case R_0280DC_CB_COLOR7_TILE:
    1228           0 :                 tmp = (reg - R_0280C0_CB_COLOR0_TILE) / 4;
    1229           0 :                 if (!radeon_cs_packet_next_is_pkt3_nop(p)) {
    1230           0 :                         if (!track->cb_color_base_last[tmp]) {
    1231           0 :                                 dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
    1232           0 :                                 return -EINVAL;
    1233             :                         }
    1234           0 :                         track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp];
    1235           0 :                         track->cb_color_tile_offset[tmp] = track->cb_color_bo_offset[tmp];
    1236           0 :                         ib[idx] = track->cb_color_base_last[tmp];
    1237           0 :                 } else {
    1238           0 :                         r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1239           0 :                         if (r) {
    1240           0 :                                 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
    1241           0 :                                 return -EINVAL;
    1242             :                         }
    1243           0 :                         track->cb_color_tile_bo[tmp] = reloc->robj;
    1244           0 :                         track->cb_color_tile_offset[tmp] = (u64)ib[idx] << 8;
    1245           0 :                         ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
    1246             :                 }
    1247           0 :                 if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
    1248           0 :                         track->cb_dirty = true;
    1249           0 :                 }
    1250             :                 break;
    1251             :         case R_028100_CB_COLOR0_MASK:
    1252             :         case R_028104_CB_COLOR1_MASK:
    1253             :         case R_028108_CB_COLOR2_MASK:
    1254             :         case R_02810C_CB_COLOR3_MASK:
    1255             :         case R_028110_CB_COLOR4_MASK:
    1256             :         case R_028114_CB_COLOR5_MASK:
    1257             :         case R_028118_CB_COLOR6_MASK:
    1258             :         case R_02811C_CB_COLOR7_MASK:
    1259           0 :                 tmp = (reg - R_028100_CB_COLOR0_MASK) / 4;
    1260           0 :                 track->cb_color_mask[tmp] = radeon_get_ib_value(p, idx);
    1261           0 :                 if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
    1262           0 :                         track->cb_dirty = true;
    1263           0 :                 }
    1264             :                 break;
    1265             :         case CB_COLOR0_BASE:
    1266             :         case CB_COLOR1_BASE:
    1267             :         case CB_COLOR2_BASE:
    1268             :         case CB_COLOR3_BASE:
    1269             :         case CB_COLOR4_BASE:
    1270             :         case CB_COLOR5_BASE:
    1271             :         case CB_COLOR6_BASE:
    1272             :         case CB_COLOR7_BASE:
    1273           0 :                 r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1274           0 :                 if (r) {
    1275           0 :                         dev_warn(p->dev, "bad SET_CONTEXT_REG "
    1276             :                                         "0x%04X\n", reg);
    1277           0 :                         return -EINVAL;
    1278             :                 }
    1279           0 :                 tmp = (reg - CB_COLOR0_BASE) / 4;
    1280           0 :                 track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
    1281           0 :                 ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
    1282           0 :                 track->cb_color_base_last[tmp] = ib[idx];
    1283           0 :                 track->cb_color_bo[tmp] = reloc->robj;
    1284           0 :                 track->cb_color_bo_mc[tmp] = reloc->gpu_offset;
    1285           0 :                 track->cb_dirty = true;
    1286           0 :                 break;
    1287             :         case DB_DEPTH_BASE:
    1288           0 :                 r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1289           0 :                 if (r) {
    1290           0 :                         dev_warn(p->dev, "bad SET_CONTEXT_REG "
    1291             :                                         "0x%04X\n", reg);
    1292           0 :                         return -EINVAL;
    1293             :                 }
    1294           0 :                 track->db_offset = radeon_get_ib_value(p, idx) << 8;
    1295           0 :                 ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
    1296           0 :                 track->db_bo = reloc->robj;
    1297           0 :                 track->db_bo_mc = reloc->gpu_offset;
    1298           0 :                 track->db_dirty = true;
    1299           0 :                 break;
    1300             :         case DB_HTILE_DATA_BASE:
    1301           0 :                 r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1302           0 :                 if (r) {
    1303           0 :                         dev_warn(p->dev, "bad SET_CONTEXT_REG "
    1304             :                                         "0x%04X\n", reg);
    1305           0 :                         return -EINVAL;
    1306             :                 }
    1307           0 :                 track->htile_offset = radeon_get_ib_value(p, idx) << 8;
    1308           0 :                 ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
    1309           0 :                 track->htile_bo = reloc->robj;
    1310           0 :                 track->db_dirty = true;
    1311           0 :                 break;
    1312             :         case DB_HTILE_SURFACE:
    1313           0 :                 track->htile_surface = radeon_get_ib_value(p, idx);
    1314             :                 /* force 8x8 htile width and height */
    1315           0 :                 ib[idx] |= 3;
    1316           0 :                 track->db_dirty = true;
    1317           0 :                 break;
    1318             :         case SQ_PGM_START_FS:
    1319             :         case SQ_PGM_START_ES:
    1320             :         case SQ_PGM_START_VS:
    1321             :         case SQ_PGM_START_GS:
    1322             :         case SQ_PGM_START_PS:
    1323             :         case SQ_ALU_CONST_CACHE_GS_0:
    1324             :         case SQ_ALU_CONST_CACHE_GS_1:
    1325             :         case SQ_ALU_CONST_CACHE_GS_2:
    1326             :         case SQ_ALU_CONST_CACHE_GS_3:
    1327             :         case SQ_ALU_CONST_CACHE_GS_4:
    1328             :         case SQ_ALU_CONST_CACHE_GS_5:
    1329             :         case SQ_ALU_CONST_CACHE_GS_6:
    1330             :         case SQ_ALU_CONST_CACHE_GS_7:
    1331             :         case SQ_ALU_CONST_CACHE_GS_8:
    1332             :         case SQ_ALU_CONST_CACHE_GS_9:
    1333             :         case SQ_ALU_CONST_CACHE_GS_10:
    1334             :         case SQ_ALU_CONST_CACHE_GS_11:
    1335             :         case SQ_ALU_CONST_CACHE_GS_12:
    1336             :         case SQ_ALU_CONST_CACHE_GS_13:
    1337             :         case SQ_ALU_CONST_CACHE_GS_14:
    1338             :         case SQ_ALU_CONST_CACHE_GS_15:
    1339             :         case SQ_ALU_CONST_CACHE_PS_0:
    1340             :         case SQ_ALU_CONST_CACHE_PS_1:
    1341             :         case SQ_ALU_CONST_CACHE_PS_2:
    1342             :         case SQ_ALU_CONST_CACHE_PS_3:
    1343             :         case SQ_ALU_CONST_CACHE_PS_4:
    1344             :         case SQ_ALU_CONST_CACHE_PS_5:
    1345             :         case SQ_ALU_CONST_CACHE_PS_6:
    1346             :         case SQ_ALU_CONST_CACHE_PS_7:
    1347             :         case SQ_ALU_CONST_CACHE_PS_8:
    1348             :         case SQ_ALU_CONST_CACHE_PS_9:
    1349             :         case SQ_ALU_CONST_CACHE_PS_10:
    1350             :         case SQ_ALU_CONST_CACHE_PS_11:
    1351             :         case SQ_ALU_CONST_CACHE_PS_12:
    1352             :         case SQ_ALU_CONST_CACHE_PS_13:
    1353             :         case SQ_ALU_CONST_CACHE_PS_14:
    1354             :         case SQ_ALU_CONST_CACHE_PS_15:
    1355             :         case SQ_ALU_CONST_CACHE_VS_0:
    1356             :         case SQ_ALU_CONST_CACHE_VS_1:
    1357             :         case SQ_ALU_CONST_CACHE_VS_2:
    1358             :         case SQ_ALU_CONST_CACHE_VS_3:
    1359             :         case SQ_ALU_CONST_CACHE_VS_4:
    1360             :         case SQ_ALU_CONST_CACHE_VS_5:
    1361             :         case SQ_ALU_CONST_CACHE_VS_6:
    1362             :         case SQ_ALU_CONST_CACHE_VS_7:
    1363             :         case SQ_ALU_CONST_CACHE_VS_8:
    1364             :         case SQ_ALU_CONST_CACHE_VS_9:
    1365             :         case SQ_ALU_CONST_CACHE_VS_10:
    1366             :         case SQ_ALU_CONST_CACHE_VS_11:
    1367             :         case SQ_ALU_CONST_CACHE_VS_12:
    1368             :         case SQ_ALU_CONST_CACHE_VS_13:
    1369             :         case SQ_ALU_CONST_CACHE_VS_14:
    1370             :         case SQ_ALU_CONST_CACHE_VS_15:
    1371           0 :                 r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1372           0 :                 if (r) {
    1373           0 :                         dev_warn(p->dev, "bad SET_CONTEXT_REG "
    1374             :                                         "0x%04X\n", reg);
    1375           0 :                         return -EINVAL;
    1376             :                 }
    1377           0 :                 ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
    1378           0 :                 break;
    1379             :         case SX_MEMORY_EXPORT_BASE:
    1380           0 :                 r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1381           0 :                 if (r) {
    1382           0 :                         dev_warn(p->dev, "bad SET_CONFIG_REG "
    1383             :                                         "0x%04X\n", reg);
    1384           0 :                         return -EINVAL;
    1385             :                 }
    1386           0 :                 ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
    1387           0 :                 break;
    1388             :         case SX_MISC:
    1389           0 :                 track->sx_misc_kill_all_prims = (radeon_get_ib_value(p, idx) & 0x1) != 0;
    1390           0 :                 break;
    1391             :         default:
    1392           0 :                 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
    1393           0 :                 return -EINVAL;
    1394             :         }
    1395           0 :         return 0;
    1396           0 : }
    1397             : 
    1398           0 : unsigned r600_mip_minify(unsigned size, unsigned level)
    1399             : {
    1400             :         unsigned val;
    1401             : 
    1402           0 :         val = max(1U, size >> level);
    1403           0 :         if (level > 0)
    1404           0 :                 val = roundup_pow_of_two(val);
    1405           0 :         return val;
    1406             : }
    1407             : 
    1408           0 : static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel,
    1409             :                               unsigned w0, unsigned h0, unsigned d0, unsigned nsamples, unsigned format,
    1410             :                               unsigned block_align, unsigned height_align, unsigned base_align,
    1411             :                               unsigned *l0_size, unsigned *mipmap_size)
    1412             : {
    1413             :         unsigned offset, i, level;
    1414             :         unsigned width, height, depth, size;
    1415             :         unsigned blocksize;
    1416             :         unsigned nbx, nby;
    1417           0 :         unsigned nlevels = llevel - blevel + 1;
    1418             : 
    1419           0 :         *l0_size = -1;
    1420           0 :         blocksize = r600_fmt_get_blocksize(format);
    1421             : 
    1422           0 :         w0 = r600_mip_minify(w0, 0);
    1423           0 :         h0 = r600_mip_minify(h0, 0);
    1424           0 :         d0 = r600_mip_minify(d0, 0);
    1425           0 :         for(i = 0, offset = 0, level = blevel; i < nlevels; i++, level++) {
    1426           0 :                 width = r600_mip_minify(w0, i);
    1427           0 :                 nbx = r600_fmt_get_nblocksx(format, width);
    1428             : 
    1429           0 :                 nbx = round_up(nbx, block_align);
    1430             : 
    1431           0 :                 height = r600_mip_minify(h0, i);
    1432           0 :                 nby = r600_fmt_get_nblocksy(format, height);
    1433           0 :                 nby = round_up(nby, height_align);
    1434             : 
    1435           0 :                 depth = r600_mip_minify(d0, i);
    1436             : 
    1437           0 :                 size = nbx * nby * blocksize * nsamples;
    1438           0 :                 if (nfaces)
    1439           0 :                         size *= nfaces;
    1440             :                 else
    1441           0 :                         size *= depth;
    1442             : 
    1443           0 :                 if (i == 0)
    1444           0 :                         *l0_size = size;
    1445             : 
    1446           0 :                 if (i == 0 || i == 1)
    1447           0 :                         offset = round_up(offset, base_align);
    1448             : 
    1449           0 :                 offset += size;
    1450             :         }
    1451           0 :         *mipmap_size = offset;
    1452           0 :         if (llevel == 0)
    1453           0 :                 *mipmap_size = *l0_size;
    1454           0 :         if (!blevel)
    1455           0 :                 *mipmap_size -= *l0_size;
    1456           0 : }
    1457             : 
    1458             : /**
    1459             :  * r600_check_texture_resource() - check if register is authorized or not
    1460             :  * @p: parser structure holding parsing context
    1461             :  * @idx: index into the cs buffer
    1462             :  * @texture: texture's bo structure
    1463             :  * @mipmap: mipmap's bo structure
    1464             :  *
    1465             :  * This function will check that the resource has valid field and that
    1466             :  * the texture and mipmap bo object are big enough to cover this resource.
    1467             :  */
    1468           0 : static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
    1469             :                                               struct radeon_bo *texture,
    1470             :                                               struct radeon_bo *mipmap,
    1471             :                                               u64 base_offset,
    1472             :                                               u64 mip_offset,
    1473             :                                               u32 tiling_flags)
    1474             : {
    1475           0 :         struct r600_cs_track *track = p->track;
    1476             :         u32 dim, nfaces, llevel, blevel, w0, h0, d0;
    1477           0 :         u32 word0, word1, l0_size, mipmap_size, word2, word3, word4, word5;
    1478           0 :         u32 height_align, pitch, pitch_align, depth_align;
    1479             :         u32 barray, larray;
    1480           0 :         u64 base_align;
    1481           0 :         struct array_mode_checker array_check;
    1482             :         u32 format;
    1483             :         bool is_array;
    1484             : 
    1485             :         /* on legacy kernel we don't perform advanced check */
    1486           0 :         if (p->rdev == NULL)
    1487           0 :                 return 0;
    1488             : 
    1489             :         /* convert to bytes */
    1490           0 :         base_offset <<= 8;
    1491           0 :         mip_offset <<= 8;
    1492             : 
    1493           0 :         word0 = radeon_get_ib_value(p, idx + 0);
    1494           0 :         if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
    1495           0 :                 if (tiling_flags & RADEON_TILING_MACRO)
    1496           0 :                         word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
    1497           0 :                 else if (tiling_flags & RADEON_TILING_MICRO)
    1498           0 :                         word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
    1499             :         }
    1500           0 :         word1 = radeon_get_ib_value(p, idx + 1);
    1501           0 :         word2 = radeon_get_ib_value(p, idx + 2) << 8;
    1502           0 :         word3 = radeon_get_ib_value(p, idx + 3) << 8;
    1503           0 :         word4 = radeon_get_ib_value(p, idx + 4);
    1504           0 :         word5 = radeon_get_ib_value(p, idx + 5);
    1505           0 :         dim = G_038000_DIM(word0);
    1506           0 :         w0 = G_038000_TEX_WIDTH(word0) + 1;
    1507           0 :         pitch = (G_038000_PITCH(word0) + 1) * 8;
    1508           0 :         h0 = G_038004_TEX_HEIGHT(word1) + 1;
    1509           0 :         d0 = G_038004_TEX_DEPTH(word1);
    1510           0 :         format = G_038004_DATA_FORMAT(word1);
    1511           0 :         blevel = G_038010_BASE_LEVEL(word4);
    1512           0 :         llevel = G_038014_LAST_LEVEL(word5);
    1513             :         /* pitch in texels */
    1514           0 :         array_check.array_mode = G_038000_TILE_MODE(word0);
    1515           0 :         array_check.group_size = track->group_size;
    1516           0 :         array_check.nbanks = track->nbanks;
    1517           0 :         array_check.npipes = track->npipes;
    1518           0 :         array_check.nsamples = 1;
    1519           0 :         array_check.blocksize = r600_fmt_get_blocksize(format);
    1520             :         nfaces = 1;
    1521             :         is_array = false;
    1522           0 :         switch (dim) {
    1523             :         case V_038000_SQ_TEX_DIM_1D:
    1524             :         case V_038000_SQ_TEX_DIM_2D:
    1525             :         case V_038000_SQ_TEX_DIM_3D:
    1526             :                 break;
    1527             :         case V_038000_SQ_TEX_DIM_CUBEMAP:
    1528           0 :                 if (p->family >= CHIP_RV770)
    1529           0 :                         nfaces = 8;
    1530             :                 else
    1531             :                         nfaces = 6;
    1532             :                 break;
    1533             :         case V_038000_SQ_TEX_DIM_1D_ARRAY:
    1534             :         case V_038000_SQ_TEX_DIM_2D_ARRAY:
    1535             :                 is_array = true;
    1536           0 :                 break;
    1537             :         case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA:
    1538           0 :                 is_array = true;
    1539             :                 /* fall through */
    1540             :         case V_038000_SQ_TEX_DIM_2D_MSAA:
    1541           0 :                 array_check.nsamples = 1 << llevel;
    1542             :                 llevel = 0;
    1543           0 :                 break;
    1544             :         default:
    1545           0 :                 dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0));
    1546           0 :                 return -EINVAL;
    1547             :         }
    1548           0 :         if (!r600_fmt_is_valid_texture(format, p->family)) {
    1549           0 :                 dev_warn(p->dev, "%s:%d texture invalid format %d\n",
    1550             :                          __func__, __LINE__, format);
    1551           0 :                 return -EINVAL;
    1552             :         }
    1553             : 
    1554           0 :         if (r600_get_array_mode_alignment(&array_check,
    1555             :                                           &pitch_align, &height_align, &depth_align, &base_align)) {
    1556           0 :                 dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n",
    1557             :                          __func__, __LINE__, G_038000_TILE_MODE(word0));
    1558           0 :                 return -EINVAL;
    1559             :         }
    1560             : 
    1561             :         /* XXX check height as well... */
    1562             : 
    1563           0 :         if (!IS_ALIGNED(pitch, pitch_align)) {
    1564           0 :                 dev_warn(p->dev, "%s:%d tex pitch (%d, 0x%x, %d) invalid\n",
    1565             :                          __func__, __LINE__, pitch, pitch_align, G_038000_TILE_MODE(word0));
    1566           0 :                 return -EINVAL;
    1567             :         }
    1568           0 :         if (!IS_ALIGNED(base_offset, base_align)) {
    1569           0 :                 dev_warn(p->dev, "%s:%d tex base offset (0x%llx, 0x%llx, %d) invalid\n",
    1570             :                          __func__, __LINE__, base_offset, base_align, G_038000_TILE_MODE(word0));
    1571           0 :                 return -EINVAL;
    1572             :         }
    1573           0 :         if (!IS_ALIGNED(mip_offset, base_align)) {
    1574           0 :                 dev_warn(p->dev, "%s:%d tex mip offset (0x%llx, 0x%llx, %d) invalid\n",
    1575             :                          __func__, __LINE__, mip_offset, base_align, G_038000_TILE_MODE(word0));
    1576           0 :                 return -EINVAL;
    1577             :         }
    1578             : 
    1579           0 :         if (blevel > llevel) {
    1580           0 :                 dev_warn(p->dev, "texture blevel %d > llevel %d\n",
    1581             :                          blevel, llevel);
    1582           0 :         }
    1583           0 :         if (is_array) {
    1584           0 :                 barray = G_038014_BASE_ARRAY(word5);
    1585           0 :                 larray = G_038014_LAST_ARRAY(word5);
    1586             : 
    1587           0 :                 nfaces = larray - barray + 1;
    1588           0 :         }
    1589           0 :         r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, array_check.nsamples, format,
    1590           0 :                           pitch_align, height_align, base_align,
    1591             :                           &l0_size, &mipmap_size);
    1592             :         /* using get ib will give us the offset into the texture bo */
    1593           0 :         if ((l0_size + word2) > radeon_bo_size(texture)) {
    1594           0 :                 dev_warn(p->dev, "texture bo too small ((%d %d) (%d %d) %d %d %d -> %d have %ld)\n",
    1595             :                          w0, h0, pitch_align, height_align,
    1596             :                          array_check.array_mode, format, word2,
    1597             :                          l0_size, radeon_bo_size(texture));
    1598           0 :                 dev_warn(p->dev, "alignments %d %d %d %lld\n", pitch, pitch_align, height_align, base_align);
    1599           0 :                 return -EINVAL;
    1600             :         }
    1601             :         /* using get ib will give us the offset into the mipmap bo */
    1602           0 :         if ((mipmap_size + word3) > radeon_bo_size(mipmap)) {
    1603             :                 /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",
    1604             :                   w0, h0, format, blevel, nlevels, word3, mipmap_size, radeon_bo_size(texture));*/
    1605             :         }
    1606           0 :         return 0;
    1607           0 : }
    1608             : 
    1609           0 : static bool r600_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
    1610             : {
    1611             :         u32 m, i;
    1612             : 
    1613           0 :         i = (reg >> 7);
    1614           0 :         if (i >= ARRAY_SIZE(r600_reg_safe_bm)) {
    1615           0 :                 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
    1616           0 :                 return false;
    1617             :         }
    1618           0 :         m = 1 << ((reg >> 2) & 31);
    1619           0 :         if (!(r600_reg_safe_bm[i] & m))
    1620           0 :                 return true;
    1621           0 :         dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
    1622           0 :         return false;
    1623           0 : }
    1624             : 
    1625           0 : static int r600_packet3_check(struct radeon_cs_parser *p,
    1626             :                                 struct radeon_cs_packet *pkt)
    1627             : {
    1628           0 :         struct radeon_bo_list *reloc;
    1629             :         struct r600_cs_track *track;
    1630             :         volatile u32 *ib;
    1631             :         unsigned idx;
    1632             :         unsigned i;
    1633             :         unsigned start_reg, end_reg, reg;
    1634             :         int r;
    1635             :         u32 idx_value;
    1636             : 
    1637           0 :         track = (struct r600_cs_track *)p->track;
    1638           0 :         ib = p->ib.ptr;
    1639           0 :         idx = pkt->idx + 1;
    1640           0 :         idx_value = radeon_get_ib_value(p, idx);
    1641             : 
    1642           0 :         switch (pkt->opcode) {
    1643             :         case PACKET3_SET_PREDICATION:
    1644             :         {
    1645             :                 int pred_op;
    1646             :                 int tmp;
    1647             :                 uint64_t offset;
    1648             : 
    1649           0 :                 if (pkt->count != 1) {
    1650           0 :                         DRM_ERROR("bad SET PREDICATION\n");
    1651           0 :                         return -EINVAL;
    1652             :                 }
    1653             : 
    1654           0 :                 tmp = radeon_get_ib_value(p, idx + 1);
    1655           0 :                 pred_op = (tmp >> 16) & 0x7;
    1656             : 
    1657             :                 /* for the clear predicate operation */
    1658           0 :                 if (pred_op == 0)
    1659           0 :                         return 0;
    1660             : 
    1661           0 :                 if (pred_op > 2) {
    1662           0 :                         DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op);
    1663           0 :                         return -EINVAL;
    1664             :                 }
    1665             : 
    1666           0 :                 r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1667           0 :                 if (r) {
    1668           0 :                         DRM_ERROR("bad SET PREDICATION\n");
    1669           0 :                         return -EINVAL;
    1670             :                 }
    1671             : 
    1672           0 :                 offset = reloc->gpu_offset +
    1673           0 :                          (idx_value & 0xfffffff0) +
    1674           0 :                          ((u64)(tmp & 0xff) << 32);
    1675             : 
    1676           0 :                 ib[idx + 0] = offset;
    1677           0 :                 ib[idx + 1] = (tmp & 0xffffff00) | (upper_32_bits(offset) & 0xff);
    1678           0 :         }
    1679             :         break;
    1680             : 
    1681             :         case PACKET3_START_3D_CMDBUF:
    1682           0 :                 if (p->family >= CHIP_RV770 || pkt->count) {
    1683           0 :                         DRM_ERROR("bad START_3D\n");
    1684           0 :                         return -EINVAL;
    1685             :                 }
    1686             :                 break;
    1687             :         case PACKET3_CONTEXT_CONTROL:
    1688           0 :                 if (pkt->count != 1) {
    1689           0 :                         DRM_ERROR("bad CONTEXT_CONTROL\n");
    1690           0 :                         return -EINVAL;
    1691             :                 }
    1692             :                 break;
    1693             :         case PACKET3_INDEX_TYPE:
    1694             :         case PACKET3_NUM_INSTANCES:
    1695           0 :                 if (pkt->count) {
    1696           0 :                         DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES\n");
    1697           0 :                         return -EINVAL;
    1698             :                 }
    1699             :                 break;
    1700             :         case PACKET3_DRAW_INDEX:
    1701             :         {
    1702             :                 uint64_t offset;
    1703           0 :                 if (pkt->count != 3) {
    1704           0 :                         DRM_ERROR("bad DRAW_INDEX\n");
    1705           0 :                         return -EINVAL;
    1706             :                 }
    1707           0 :                 r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1708           0 :                 if (r) {
    1709           0 :                         DRM_ERROR("bad DRAW_INDEX\n");
    1710           0 :                         return -EINVAL;
    1711             :                 }
    1712             : 
    1713           0 :                 offset = reloc->gpu_offset +
    1714           0 :                          idx_value +
    1715           0 :                          ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32);
    1716             : 
    1717           0 :                 ib[idx+0] = offset;
    1718           0 :                 ib[idx+1] = upper_32_bits(offset) & 0xff;
    1719             : 
    1720           0 :                 r = r600_cs_track_check(p);
    1721           0 :                 if (r) {
    1722           0 :                         dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
    1723           0 :                         return r;
    1724             :                 }
    1725           0 :                 break;
    1726             :         }
    1727             :         case PACKET3_DRAW_INDEX_AUTO:
    1728           0 :                 if (pkt->count != 1) {
    1729           0 :                         DRM_ERROR("bad DRAW_INDEX_AUTO\n");
    1730           0 :                         return -EINVAL;
    1731             :                 }
    1732           0 :                 r = r600_cs_track_check(p);
    1733           0 :                 if (r) {
    1734           0 :                         dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
    1735           0 :                         return r;
    1736             :                 }
    1737             :                 break;
    1738             :         case PACKET3_DRAW_INDEX_IMMD_BE:
    1739             :         case PACKET3_DRAW_INDEX_IMMD:
    1740           0 :                 if (pkt->count < 2) {
    1741           0 :                         DRM_ERROR("bad DRAW_INDEX_IMMD\n");
    1742           0 :                         return -EINVAL;
    1743             :                 }
    1744           0 :                 r = r600_cs_track_check(p);
    1745           0 :                 if (r) {
    1746           0 :                         dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
    1747           0 :                         return r;
    1748             :                 }
    1749             :                 break;
    1750             :         case PACKET3_WAIT_REG_MEM:
    1751           0 :                 if (pkt->count != 5) {
    1752           0 :                         DRM_ERROR("bad WAIT_REG_MEM\n");
    1753           0 :                         return -EINVAL;
    1754             :                 }
    1755             :                 /* bit 4 is reg (0) or mem (1) */
    1756           0 :                 if (idx_value & 0x10) {
    1757             :                         uint64_t offset;
    1758             : 
    1759           0 :                         r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1760           0 :                         if (r) {
    1761           0 :                                 DRM_ERROR("bad WAIT_REG_MEM\n");
    1762           0 :                                 return -EINVAL;
    1763             :                         }
    1764             : 
    1765           0 :                         offset = reloc->gpu_offset +
    1766           0 :                                  (radeon_get_ib_value(p, idx+1) & 0xfffffff0) +
    1767           0 :                                  ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
    1768             : 
    1769           0 :                         ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffff0);
    1770           0 :                         ib[idx+2] = upper_32_bits(offset) & 0xff;
    1771           0 :                 } else if (idx_value & 0x100) {
    1772           0 :                         DRM_ERROR("cannot use PFP on REG wait\n");
    1773           0 :                         return -EINVAL;
    1774             :                 }
    1775             :                 break;
    1776             :         case PACKET3_CP_DMA:
    1777             :         {
    1778             :                 u32 command, size;
    1779             :                 u64 offset, tmp;
    1780           0 :                 if (pkt->count != 4) {
    1781           0 :                         DRM_ERROR("bad CP DMA\n");
    1782           0 :                         return -EINVAL;
    1783             :                 }
    1784           0 :                 command = radeon_get_ib_value(p, idx+4);
    1785           0 :                 size = command & 0x1fffff;
    1786           0 :                 if (command & PACKET3_CP_DMA_CMD_SAS) {
    1787             :                         /* src address space is register */
    1788           0 :                         DRM_ERROR("CP DMA SAS not supported\n");
    1789           0 :                         return -EINVAL;
    1790             :                 } else {
    1791           0 :                         if (command & PACKET3_CP_DMA_CMD_SAIC) {
    1792           0 :                                 DRM_ERROR("CP DMA SAIC only supported for registers\n");
    1793           0 :                                 return -EINVAL;
    1794             :                         }
    1795             :                         /* src address space is memory */
    1796           0 :                         r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1797           0 :                         if (r) {
    1798           0 :                                 DRM_ERROR("bad CP DMA SRC\n");
    1799           0 :                                 return -EINVAL;
    1800             :                         }
    1801             : 
    1802           0 :                         tmp = radeon_get_ib_value(p, idx) +
    1803           0 :                                 ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32);
    1804             : 
    1805           0 :                         offset = reloc->gpu_offset + tmp;
    1806             : 
    1807           0 :                         if ((tmp + size) > radeon_bo_size(reloc->robj)) {
    1808           0 :                                 dev_warn(p->dev, "CP DMA src buffer too small (%llu %lu)\n",
    1809             :                                          tmp + size, radeon_bo_size(reloc->robj));
    1810           0 :                                 return -EINVAL;
    1811             :                         }
    1812             : 
    1813           0 :                         ib[idx] = offset;
    1814           0 :                         ib[idx+1] = (ib[idx+1] & 0xffffff00) | (upper_32_bits(offset) & 0xff);
    1815             :                 }
    1816           0 :                 if (command & PACKET3_CP_DMA_CMD_DAS) {
    1817             :                         /* dst address space is register */
    1818           0 :                         DRM_ERROR("CP DMA DAS not supported\n");
    1819           0 :                         return -EINVAL;
    1820             :                 } else {
    1821             :                         /* dst address space is memory */
    1822           0 :                         if (command & PACKET3_CP_DMA_CMD_DAIC) {
    1823           0 :                                 DRM_ERROR("CP DMA DAIC only supported for registers\n");
    1824           0 :                                 return -EINVAL;
    1825             :                         }
    1826           0 :                         r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1827           0 :                         if (r) {
    1828           0 :                                 DRM_ERROR("bad CP DMA DST\n");
    1829           0 :                                 return -EINVAL;
    1830             :                         }
    1831             : 
    1832           0 :                         tmp = radeon_get_ib_value(p, idx+2) +
    1833           0 :                                 ((u64)(radeon_get_ib_value(p, idx+3) & 0xff) << 32);
    1834             : 
    1835           0 :                         offset = reloc->gpu_offset + tmp;
    1836             : 
    1837           0 :                         if ((tmp + size) > radeon_bo_size(reloc->robj)) {
    1838           0 :                                 dev_warn(p->dev, "CP DMA dst buffer too small (%llu %lu)\n",
    1839             :                                          tmp + size, radeon_bo_size(reloc->robj));
    1840           0 :                                 return -EINVAL;
    1841             :                         }
    1842             : 
    1843           0 :                         ib[idx+2] = offset;
    1844           0 :                         ib[idx+3] = upper_32_bits(offset) & 0xff;
    1845             :                 }
    1846           0 :                 break;
    1847             :         }
    1848             :         case PACKET3_SURFACE_SYNC:
    1849           0 :                 if (pkt->count != 3) {
    1850           0 :                         DRM_ERROR("bad SURFACE_SYNC\n");
    1851           0 :                         return -EINVAL;
    1852             :                 }
    1853             :                 /* 0xffffffff/0x0 is flush all cache flag */
    1854           0 :                 if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
    1855           0 :                     radeon_get_ib_value(p, idx + 2) != 0) {
    1856           0 :                         r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1857           0 :                         if (r) {
    1858           0 :                                 DRM_ERROR("bad SURFACE_SYNC\n");
    1859           0 :                                 return -EINVAL;
    1860             :                         }
    1861           0 :                         ib[idx+2] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
    1862           0 :                 }
    1863             :                 break;
    1864             :         case PACKET3_EVENT_WRITE:
    1865           0 :                 if (pkt->count != 2 && pkt->count != 0) {
    1866           0 :                         DRM_ERROR("bad EVENT_WRITE\n");
    1867           0 :                         return -EINVAL;
    1868             :                 }
    1869           0 :                 if (pkt->count) {
    1870             :                         uint64_t offset;
    1871             : 
    1872           0 :                         r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1873           0 :                         if (r) {
    1874           0 :                                 DRM_ERROR("bad EVENT_WRITE\n");
    1875           0 :                                 return -EINVAL;
    1876             :                         }
    1877           0 :                         offset = reloc->gpu_offset +
    1878           0 :                                  (radeon_get_ib_value(p, idx+1) & 0xfffffff8) +
    1879           0 :                                  ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
    1880             : 
    1881           0 :                         ib[idx+1] = offset & 0xfffffff8;
    1882           0 :                         ib[idx+2] = upper_32_bits(offset) & 0xff;
    1883           0 :                 }
    1884             :                 break;
    1885             :         case PACKET3_EVENT_WRITE_EOP:
    1886             :         {
    1887             :                 uint64_t offset;
    1888             : 
    1889           0 :                 if (pkt->count != 4) {
    1890           0 :                         DRM_ERROR("bad EVENT_WRITE_EOP\n");
    1891           0 :                         return -EINVAL;
    1892             :                 }
    1893           0 :                 r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1894           0 :                 if (r) {
    1895           0 :                         DRM_ERROR("bad EVENT_WRITE\n");
    1896           0 :                         return -EINVAL;
    1897             :                 }
    1898             : 
    1899           0 :                 offset = reloc->gpu_offset +
    1900           0 :                          (radeon_get_ib_value(p, idx+1) & 0xfffffffc) +
    1901           0 :                          ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
    1902             : 
    1903           0 :                 ib[idx+1] = offset & 0xfffffffc;
    1904           0 :                 ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff);
    1905           0 :                 break;
    1906             :         }
    1907             :         case PACKET3_SET_CONFIG_REG:
    1908           0 :                 start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_OFFSET;
    1909           0 :                 end_reg = 4 * pkt->count + start_reg - 4;
    1910           0 :                 if ((start_reg < PACKET3_SET_CONFIG_REG_OFFSET) ||
    1911           0 :                     (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
    1912           0 :                     (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
    1913           0 :                         DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
    1914           0 :                         return -EINVAL;
    1915             :                 }
    1916           0 :                 for (i = 0; i < pkt->count; i++) {
    1917           0 :                         reg = start_reg + (4 * i);
    1918           0 :                         r = r600_cs_check_reg(p, reg, idx+1+i);
    1919           0 :                         if (r)
    1920           0 :                                 return r;
    1921             :                 }
    1922             :                 break;
    1923             :         case PACKET3_SET_CONTEXT_REG:
    1924           0 :                 start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_OFFSET;
    1925           0 :                 end_reg = 4 * pkt->count + start_reg - 4;
    1926           0 :                 if ((start_reg < PACKET3_SET_CONTEXT_REG_OFFSET) ||
    1927           0 :                     (start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
    1928           0 :                     (end_reg >= PACKET3_SET_CONTEXT_REG_END)) {
    1929           0 :                         DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");
    1930           0 :                         return -EINVAL;
    1931             :                 }
    1932           0 :                 for (i = 0; i < pkt->count; i++) {
    1933           0 :                         reg = start_reg + (4 * i);
    1934           0 :                         r = r600_cs_check_reg(p, reg, idx+1+i);
    1935           0 :                         if (r)
    1936           0 :                                 return r;
    1937             :                 }
    1938             :                 break;
    1939             :         case PACKET3_SET_RESOURCE:
    1940           0 :                 if (pkt->count % 7) {
    1941           0 :                         DRM_ERROR("bad SET_RESOURCE\n");
    1942           0 :                         return -EINVAL;
    1943             :                 }
    1944           0 :                 start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_OFFSET;
    1945           0 :                 end_reg = 4 * pkt->count + start_reg - 4;
    1946           0 :                 if ((start_reg < PACKET3_SET_RESOURCE_OFFSET) ||
    1947           0 :                     (start_reg >= PACKET3_SET_RESOURCE_END) ||
    1948           0 :                     (end_reg >= PACKET3_SET_RESOURCE_END)) {
    1949           0 :                         DRM_ERROR("bad SET_RESOURCE\n");
    1950           0 :                         return -EINVAL;
    1951             :                 }
    1952           0 :                 for (i = 0; i < (pkt->count / 7); i++) {
    1953             :                         struct radeon_bo *texture, *mipmap;
    1954             :                         u32 size, offset, base_offset, mip_offset;
    1955             : 
    1956           0 :                         switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) {
    1957             :                         case SQ_TEX_VTX_VALID_TEXTURE:
    1958             :                                 /* tex base */
    1959           0 :                                 r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1960           0 :                                 if (r) {
    1961           0 :                                         DRM_ERROR("bad SET_RESOURCE\n");
    1962           0 :                                         return -EINVAL;
    1963             :                                 }
    1964           0 :                                 base_offset = (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
    1965           0 :                                 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
    1966           0 :                                         if (reloc->tiling_flags & RADEON_TILING_MACRO)
    1967           0 :                                                 ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
    1968           0 :                                         else if (reloc->tiling_flags & RADEON_TILING_MICRO)
    1969           0 :                                                 ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
    1970             :                                 }
    1971           0 :                                 texture = reloc->robj;
    1972             :                                 /* tex mip base */
    1973           0 :                                 r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1974           0 :                                 if (r) {
    1975           0 :                                         DRM_ERROR("bad SET_RESOURCE\n");
    1976           0 :                                         return -EINVAL;
    1977             :                                 }
    1978           0 :                                 mip_offset = (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
    1979           0 :                                 mipmap = reloc->robj;
    1980           0 :                                 r = r600_check_texture_resource(p,  idx+(i*7)+1,
    1981             :                                                                 texture, mipmap,
    1982           0 :                                                                 base_offset + radeon_get_ib_value(p, idx+1+(i*7)+2),
    1983           0 :                                                                 mip_offset + radeon_get_ib_value(p, idx+1+(i*7)+3),
    1984           0 :                                                                 reloc->tiling_flags);
    1985           0 :                                 if (r)
    1986           0 :                                         return r;
    1987           0 :                                 ib[idx+1+(i*7)+2] += base_offset;
    1988           0 :                                 ib[idx+1+(i*7)+3] += mip_offset;
    1989           0 :                                 break;
    1990             :                         case SQ_TEX_VTX_VALID_BUFFER:
    1991             :                         {
    1992             :                                 uint64_t offset64;
    1993             :                                 /* vtx base */
    1994           0 :                                 r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    1995           0 :                                 if (r) {
    1996           0 :                                         DRM_ERROR("bad SET_RESOURCE\n");
    1997           0 :                                         return -EINVAL;
    1998             :                                 }
    1999           0 :                                 offset = radeon_get_ib_value(p, idx+1+(i*7)+0);
    2000           0 :                                 size = radeon_get_ib_value(p, idx+1+(i*7)+1) + 1;
    2001           0 :                                 if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
    2002             :                                         /* force size to size of the buffer */
    2003           0 :                                         dev_warn(p->dev, "vbo resource seems too big (%d) for the bo (%ld)\n",
    2004             :                                                  size + offset, radeon_bo_size(reloc->robj));
    2005           0 :                                         ib[idx+1+(i*7)+1] = radeon_bo_size(reloc->robj) - offset;
    2006           0 :                                 }
    2007             : 
    2008           0 :                                 offset64 = reloc->gpu_offset + offset;
    2009           0 :                                 ib[idx+1+(i*8)+0] = offset64;
    2010           0 :                                 ib[idx+1+(i*8)+2] = (ib[idx+1+(i*8)+2] & 0xffffff00) |
    2011           0 :                                                     (upper_32_bits(offset64) & 0xff);
    2012           0 :                                 break;
    2013             :                         }
    2014             :                         case SQ_TEX_VTX_INVALID_TEXTURE:
    2015             :                         case SQ_TEX_VTX_INVALID_BUFFER:
    2016             :                         default:
    2017           0 :                                 DRM_ERROR("bad SET_RESOURCE\n");
    2018           0 :                                 return -EINVAL;
    2019             :                         }
    2020           0 :                 }
    2021             :                 break;
    2022             :         case PACKET3_SET_ALU_CONST:
    2023           0 :                 if (track->sq_config & DX9_CONSTS) {
    2024           0 :                         start_reg = (idx_value << 2) + PACKET3_SET_ALU_CONST_OFFSET;
    2025           0 :                         end_reg = 4 * pkt->count + start_reg - 4;
    2026           0 :                         if ((start_reg < PACKET3_SET_ALU_CONST_OFFSET) ||
    2027           0 :                             (start_reg >= PACKET3_SET_ALU_CONST_END) ||
    2028           0 :                             (end_reg >= PACKET3_SET_ALU_CONST_END)) {
    2029           0 :                                 DRM_ERROR("bad SET_ALU_CONST\n");
    2030           0 :                                 return -EINVAL;
    2031             :                         }
    2032             :                 }
    2033             :                 break;
    2034             :         case PACKET3_SET_BOOL_CONST:
    2035           0 :                 start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_OFFSET;
    2036           0 :                 end_reg = 4 * pkt->count + start_reg - 4;
    2037           0 :                 if ((start_reg < PACKET3_SET_BOOL_CONST_OFFSET) ||
    2038           0 :                     (start_reg >= PACKET3_SET_BOOL_CONST_END) ||
    2039           0 :                     (end_reg >= PACKET3_SET_BOOL_CONST_END)) {
    2040           0 :                         DRM_ERROR("bad SET_BOOL_CONST\n");
    2041           0 :                         return -EINVAL;
    2042             :                 }
    2043             :                 break;
    2044             :         case PACKET3_SET_LOOP_CONST:
    2045           0 :                 start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_OFFSET;
    2046           0 :                 end_reg = 4 * pkt->count + start_reg - 4;
    2047           0 :                 if ((start_reg < PACKET3_SET_LOOP_CONST_OFFSET) ||
    2048           0 :                     (start_reg >= PACKET3_SET_LOOP_CONST_END) ||
    2049           0 :                     (end_reg >= PACKET3_SET_LOOP_CONST_END)) {
    2050           0 :                         DRM_ERROR("bad SET_LOOP_CONST\n");
    2051           0 :                         return -EINVAL;
    2052             :                 }
    2053             :                 break;
    2054             :         case PACKET3_SET_CTL_CONST:
    2055           0 :                 start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_OFFSET;
    2056           0 :                 end_reg = 4 * pkt->count + start_reg - 4;
    2057           0 :                 if ((start_reg < PACKET3_SET_CTL_CONST_OFFSET) ||
    2058           0 :                     (start_reg >= PACKET3_SET_CTL_CONST_END) ||
    2059           0 :                     (end_reg >= PACKET3_SET_CTL_CONST_END)) {
    2060           0 :                         DRM_ERROR("bad SET_CTL_CONST\n");
    2061           0 :                         return -EINVAL;
    2062             :                 }
    2063             :                 break;
    2064             :         case PACKET3_SET_SAMPLER:
    2065           0 :                 if (pkt->count % 3) {
    2066           0 :                         DRM_ERROR("bad SET_SAMPLER\n");
    2067           0 :                         return -EINVAL;
    2068             :                 }
    2069           0 :                 start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_OFFSET;
    2070           0 :                 end_reg = 4 * pkt->count + start_reg - 4;
    2071           0 :                 if ((start_reg < PACKET3_SET_SAMPLER_OFFSET) ||
    2072           0 :                     (start_reg >= PACKET3_SET_SAMPLER_END) ||
    2073           0 :                     (end_reg >= PACKET3_SET_SAMPLER_END)) {
    2074           0 :                         DRM_ERROR("bad SET_SAMPLER\n");
    2075           0 :                         return -EINVAL;
    2076             :                 }
    2077             :                 break;
    2078             :         case PACKET3_STRMOUT_BASE_UPDATE:
    2079             :                 /* RS780 and RS880 also need this */
    2080           0 :                 if (p->family < CHIP_RS780) {
    2081           0 :                         DRM_ERROR("STRMOUT_BASE_UPDATE only supported on 7xx\n");
    2082           0 :                         return -EINVAL;
    2083             :                 }
    2084           0 :                 if (pkt->count != 1) {
    2085           0 :                         DRM_ERROR("bad STRMOUT_BASE_UPDATE packet count\n");
    2086           0 :                         return -EINVAL;
    2087             :                 }
    2088           0 :                 if (idx_value > 3) {
    2089           0 :                         DRM_ERROR("bad STRMOUT_BASE_UPDATE index\n");
    2090           0 :                         return -EINVAL;
    2091             :                 }
    2092             :                 {
    2093             :                         u64 offset;
    2094             : 
    2095           0 :                         r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    2096           0 :                         if (r) {
    2097           0 :                                 DRM_ERROR("bad STRMOUT_BASE_UPDATE reloc\n");
    2098           0 :                                 return -EINVAL;
    2099             :                         }
    2100             : 
    2101           0 :                         if (reloc->robj != track->vgt_strmout_bo[idx_value]) {
    2102           0 :                                 DRM_ERROR("bad STRMOUT_BASE_UPDATE, bo does not match\n");
    2103           0 :                                 return -EINVAL;
    2104             :                         }
    2105             : 
    2106           0 :                         offset = radeon_get_ib_value(p, idx+1) << 8;
    2107           0 :                         if (offset != track->vgt_strmout_bo_offset[idx_value]) {
    2108           0 :                                 DRM_ERROR("bad STRMOUT_BASE_UPDATE, bo offset does not match: 0x%llx, 0x%x\n",
    2109             :                                           offset, track->vgt_strmout_bo_offset[idx_value]);
    2110           0 :                                 return -EINVAL;
    2111             :                         }
    2112             : 
    2113           0 :                         if ((offset + 4) > radeon_bo_size(reloc->robj)) {
    2114           0 :                                 DRM_ERROR("bad STRMOUT_BASE_UPDATE bo too small: 0x%llx, 0x%lx\n",
    2115             :                                           offset + 4, radeon_bo_size(reloc->robj));
    2116           0 :                                 return -EINVAL;
    2117             :                         }
    2118           0 :                         ib[idx+1] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
    2119           0 :                 }
    2120             :                 break;
    2121             :         case PACKET3_SURFACE_BASE_UPDATE:
    2122           0 :                 if (p->family >= CHIP_RV770 || p->family == CHIP_R600) {
    2123           0 :                         DRM_ERROR("bad SURFACE_BASE_UPDATE\n");
    2124           0 :                         return -EINVAL;
    2125             :                 }
    2126           0 :                 if (pkt->count) {
    2127           0 :                         DRM_ERROR("bad SURFACE_BASE_UPDATE\n");
    2128           0 :                         return -EINVAL;
    2129             :                 }
    2130             :                 break;
    2131             :         case PACKET3_STRMOUT_BUFFER_UPDATE:
    2132           0 :                 if (pkt->count != 4) {
    2133           0 :                         DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
    2134           0 :                         return -EINVAL;
    2135             :                 }
    2136             :                 /* Updating memory at DST_ADDRESS. */
    2137           0 :                 if (idx_value & 0x1) {
    2138             :                         u64 offset;
    2139           0 :                         r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    2140           0 :                         if (r) {
    2141           0 :                                 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n");
    2142           0 :                                 return -EINVAL;
    2143             :                         }
    2144           0 :                         offset = radeon_get_ib_value(p, idx+1);
    2145           0 :                         offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
    2146           0 :                         if ((offset + 4) > radeon_bo_size(reloc->robj)) {
    2147           0 :                                 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%llx, 0x%lx\n",
    2148             :                                           offset + 4, radeon_bo_size(reloc->robj));
    2149           0 :                                 return -EINVAL;
    2150             :                         }
    2151           0 :                         offset += reloc->gpu_offset;
    2152           0 :                         ib[idx+1] = offset;
    2153           0 :                         ib[idx+2] = upper_32_bits(offset) & 0xff;
    2154           0 :                 }
    2155             :                 /* Reading data from SRC_ADDRESS. */
    2156           0 :                 if (((idx_value >> 1) & 0x3) == 2) {
    2157             :                         u64 offset;
    2158           0 :                         r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    2159           0 :                         if (r) {
    2160           0 :                                 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n");
    2161           0 :                                 return -EINVAL;
    2162             :                         }
    2163           0 :                         offset = radeon_get_ib_value(p, idx+3);
    2164           0 :                         offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
    2165           0 :                         if ((offset + 4) > radeon_bo_size(reloc->robj)) {
    2166           0 :                                 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%llx, 0x%lx\n",
    2167             :                                           offset + 4, radeon_bo_size(reloc->robj));
    2168           0 :                                 return -EINVAL;
    2169             :                         }
    2170           0 :                         offset += reloc->gpu_offset;
    2171           0 :                         ib[idx+3] = offset;
    2172           0 :                         ib[idx+4] = upper_32_bits(offset) & 0xff;
    2173           0 :                 }
    2174             :                 break;
    2175             :         case PACKET3_MEM_WRITE:
    2176             :         {
    2177             :                 u64 offset;
    2178             : 
    2179           0 :                 if (pkt->count != 3) {
    2180           0 :                         DRM_ERROR("bad MEM_WRITE (invalid count)\n");
    2181           0 :                         return -EINVAL;
    2182             :                 }
    2183           0 :                 r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    2184           0 :                 if (r) {
    2185           0 :                         DRM_ERROR("bad MEM_WRITE (missing reloc)\n");
    2186           0 :                         return -EINVAL;
    2187             :                 }
    2188           0 :                 offset = radeon_get_ib_value(p, idx+0);
    2189           0 :                 offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL;
    2190           0 :                 if (offset & 0x7) {
    2191           0 :                         DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n");
    2192           0 :                         return -EINVAL;
    2193             :                 }
    2194           0 :                 if ((offset + 8) > radeon_bo_size(reloc->robj)) {
    2195           0 :                         DRM_ERROR("bad MEM_WRITE bo too small: 0x%llx, 0x%lx\n",
    2196             :                                   offset + 8, radeon_bo_size(reloc->robj));
    2197           0 :                         return -EINVAL;
    2198             :                 }
    2199           0 :                 offset += reloc->gpu_offset;
    2200           0 :                 ib[idx+0] = offset;
    2201           0 :                 ib[idx+1] = upper_32_bits(offset) & 0xff;
    2202           0 :                 break;
    2203             :         }
    2204             :         case PACKET3_COPY_DW:
    2205           0 :                 if (pkt->count != 4) {
    2206           0 :                         DRM_ERROR("bad COPY_DW (invalid count)\n");
    2207           0 :                         return -EINVAL;
    2208             :                 }
    2209           0 :                 if (idx_value & 0x1) {
    2210             :                         u64 offset;
    2211             :                         /* SRC is memory. */
    2212           0 :                         r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    2213           0 :                         if (r) {
    2214           0 :                                 DRM_ERROR("bad COPY_DW (missing src reloc)\n");
    2215           0 :                                 return -EINVAL;
    2216             :                         }
    2217           0 :                         offset = radeon_get_ib_value(p, idx+1);
    2218           0 :                         offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
    2219           0 :                         if ((offset + 4) > radeon_bo_size(reloc->robj)) {
    2220           0 :                                 DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n",
    2221             :                                           offset + 4, radeon_bo_size(reloc->robj));
    2222           0 :                                 return -EINVAL;
    2223             :                         }
    2224           0 :                         offset += reloc->gpu_offset;
    2225           0 :                         ib[idx+1] = offset;
    2226           0 :                         ib[idx+2] = upper_32_bits(offset) & 0xff;
    2227           0 :                 } else {
    2228             :                         /* SRC is a reg. */
    2229           0 :                         reg = radeon_get_ib_value(p, idx+1) << 2;
    2230           0 :                         if (!r600_is_safe_reg(p, reg, idx+1))
    2231           0 :                                 return -EINVAL;
    2232             :                 }
    2233           0 :                 if (idx_value & 0x2) {
    2234             :                         u64 offset;
    2235             :                         /* DST is memory. */
    2236           0 :                         r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
    2237           0 :                         if (r) {
    2238           0 :                                 DRM_ERROR("bad COPY_DW (missing dst reloc)\n");
    2239           0 :                                 return -EINVAL;
    2240             :                         }
    2241           0 :                         offset = radeon_get_ib_value(p, idx+3);
    2242           0 :                         offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
    2243           0 :                         if ((offset + 4) > radeon_bo_size(reloc->robj)) {
    2244           0 :                                 DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n",
    2245             :                                           offset + 4, radeon_bo_size(reloc->robj));
    2246           0 :                                 return -EINVAL;
    2247             :                         }
    2248           0 :                         offset += reloc->gpu_offset;
    2249           0 :                         ib[idx+3] = offset;
    2250           0 :                         ib[idx+4] = upper_32_bits(offset) & 0xff;
    2251           0 :                 } else {
    2252             :                         /* DST is a reg. */
    2253           0 :                         reg = radeon_get_ib_value(p, idx+3) << 2;
    2254           0 :                         if (!r600_is_safe_reg(p, reg, idx+3))
    2255           0 :                                 return -EINVAL;
    2256             :                 }
    2257             :                 break;
    2258             :         case PACKET3_NOP:
    2259             :                 break;
    2260             :         default:
    2261           0 :                 DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
    2262           0 :                 return -EINVAL;
    2263             :         }
    2264           0 :         return 0;
    2265           0 : }
    2266             : 
    2267           0 : int r600_cs_parse(struct radeon_cs_parser *p)
    2268             : {
    2269           0 :         struct radeon_cs_packet pkt;
    2270             :         struct r600_cs_track *track;
    2271             :         int r;
    2272             : 
    2273           0 :         if (p->track == NULL) {
    2274             :                 /* initialize tracker, we are in kms */
    2275           0 :                 track = kzalloc(sizeof(*track), GFP_KERNEL);
    2276           0 :                 if (track == NULL)
    2277           0 :                         return -ENOMEM;
    2278           0 :                 r600_cs_track_init(track);
    2279           0 :                 if (p->rdev->family < CHIP_RV770) {
    2280           0 :                         track->npipes = p->rdev->config.r600.tiling_npipes;
    2281           0 :                         track->nbanks = p->rdev->config.r600.tiling_nbanks;
    2282           0 :                         track->group_size = p->rdev->config.r600.tiling_group_size;
    2283           0 :                 } else if (p->rdev->family <= CHIP_RV740) {
    2284           0 :                         track->npipes = p->rdev->config.rv770.tiling_npipes;
    2285           0 :                         track->nbanks = p->rdev->config.rv770.tiling_nbanks;
    2286           0 :                         track->group_size = p->rdev->config.rv770.tiling_group_size;
    2287           0 :                 }
    2288           0 :                 p->track = track;
    2289           0 :         }
    2290           0 :         do {
    2291           0 :                 r = radeon_cs_packet_parse(p, &pkt, p->idx);
    2292           0 :                 if (r) {
    2293           0 :                         kfree(p->track);
    2294           0 :                         p->track = NULL;
    2295           0 :                         return r;
    2296             :                 }
    2297           0 :                 p->idx += pkt.count + 2;
    2298           0 :                 switch (pkt.type) {
    2299             :                 case RADEON_PACKET_TYPE0:
    2300           0 :                         r = r600_cs_parse_packet0(p, &pkt);
    2301           0 :                         break;
    2302             :                 case RADEON_PACKET_TYPE2:
    2303             :                         break;
    2304             :                 case RADEON_PACKET_TYPE3:
    2305           0 :                         r = r600_packet3_check(p, &pkt);
    2306           0 :                         break;
    2307             :                 default:
    2308           0 :                         DRM_ERROR("Unknown packet type %d !\n", pkt.type);
    2309           0 :                         kfree(p->track);
    2310           0 :                         p->track = NULL;
    2311           0 :                         return -EINVAL;
    2312             :                 }
    2313           0 :                 if (r) {
    2314           0 :                         kfree(p->track);
    2315           0 :                         p->track = NULL;
    2316           0 :                         return r;
    2317             :                 }
    2318           0 :         } while (p->idx < p->chunk_ib->length_dw);
    2319             : #if 0
    2320             :         for (r = 0; r < p->ib.length_dw; r++) {
    2321             :                 printk(KERN_INFO "%05d  0x%08X\n", r, p->ib.ptr[r]);
    2322             :                 mdelay(1);
    2323             :         }
    2324             : #endif
    2325           0 :         kfree(p->track);
    2326           0 :         p->track = NULL;
    2327           0 :         return 0;
    2328           0 : }
    2329             : 
    2330             : #ifdef CONFIG_DRM_RADEON_UMS
    2331             : 
    2332             : /**
    2333             :  * cs_parser_fini() - clean parser states
    2334             :  * @parser:     parser structure holding parsing context.
    2335             :  * @error:      error number
    2336             :  *
    2337             :  * If error is set than unvalidate buffer, otherwise just free memory
    2338             :  * used by parsing context.
    2339             :  **/
    2340             : static void r600_cs_parser_fini(struct radeon_cs_parser *parser, int error)
    2341             : {
    2342             :         unsigned i;
    2343             : 
    2344             :         kfree(parser->relocs);
    2345             :         for (i = 0; i < parser->nchunks; i++)
    2346             :                 drm_free_large(parser->chunks[i].kdata);
    2347             :         kfree(parser->chunks);
    2348             :         kfree(parser->chunks_array);
    2349             : }
    2350             : 
    2351             : static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p)
    2352             : {
    2353             :         if (p->chunk_relocs == NULL) {
    2354             :                 return 0;
    2355             :         }
    2356             :         p->relocs = kzalloc(sizeof(struct radeon_bo_list), GFP_KERNEL);
    2357             :         if (p->relocs == NULL) {
    2358             :                 return -ENOMEM;
    2359             :         }
    2360             :         return 0;
    2361             : }
    2362             : 
    2363             : int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
    2364             :                         unsigned family, u32 *ib, int *l)
    2365             : {
    2366             :         struct radeon_cs_parser parser;
    2367             :         struct radeon_cs_chunk *ib_chunk;
    2368             :         struct r600_cs_track *track;
    2369             :         int r;
    2370             : 
    2371             :         /* initialize tracker */
    2372             :         track = kzalloc(sizeof(*track), GFP_KERNEL);
    2373             :         if (track == NULL)
    2374             :                 return -ENOMEM;
    2375             :         r600_cs_track_init(track);
    2376             :         r600_cs_legacy_get_tiling_conf(dev, &track->npipes, &track->nbanks, &track->group_size);
    2377             :         /* initialize parser */
    2378             :         memset(&parser, 0, sizeof(struct radeon_cs_parser));
    2379             :         parser.filp = filp;
    2380             :         parser.dev = &dev->pdev->dev;
    2381             :         parser.rdev = NULL;
    2382             :         parser.family = family;
    2383             :         parser.track = track;
    2384             :         parser.ib.ptr = ib;
    2385             :         r = radeon_cs_parser_init(&parser, data);
    2386             :         if (r) {
    2387             :                 DRM_ERROR("Failed to initialize parser !\n");
    2388             :                 r600_cs_parser_fini(&parser, r);
    2389             :                 return r;
    2390             :         }
    2391             :         r = r600_cs_parser_relocs_legacy(&parser);
    2392             :         if (r) {
    2393             :                 DRM_ERROR("Failed to parse relocation !\n");
    2394             :                 r600_cs_parser_fini(&parser, r);
    2395             :                 return r;
    2396             :         }
    2397             :         /* Copy the packet into the IB, the parser will read from the
    2398             :          * input memory (cached) and write to the IB (which can be
    2399             :          * uncached). */
    2400             :         ib_chunk = parser.chunk_ib;
    2401             :         parser.ib.length_dw = ib_chunk->length_dw;
    2402             :         *l = parser.ib.length_dw;
    2403             :         if (copy_from_user(ib, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) {
    2404             :                 r = -EFAULT;
    2405             :                 r600_cs_parser_fini(&parser, r);
    2406             :                 return r;
    2407             :         }
    2408             :         r = r600_cs_parse(&parser);
    2409             :         if (r) {
    2410             :                 DRM_ERROR("Invalid command stream !\n");
    2411             :                 r600_cs_parser_fini(&parser, r);
    2412             :                 return r;
    2413             :         }
    2414             :         r600_cs_parser_fini(&parser, r);
    2415             :         return r;
    2416             : }
    2417             : 
    2418             : void r600_cs_legacy_init(void)
    2419             : {
    2420             :         r600_nomm = 1;
    2421             : }
    2422             : 
    2423             : #endif
    2424             : 
    2425             : /*
    2426             :  *  DMA
    2427             :  */
    2428             : /**
    2429             :  * r600_dma_cs_next_reloc() - parse next reloc
    2430             :  * @p:          parser structure holding parsing context.
    2431             :  * @cs_reloc:           reloc informations
    2432             :  *
    2433             :  * Return the next reloc, do bo validation and compute
    2434             :  * GPU offset using the provided start.
    2435             :  **/
    2436           0 : int r600_dma_cs_next_reloc(struct radeon_cs_parser *p,
    2437             :                            struct radeon_bo_list **cs_reloc)
    2438             : {
    2439             :         struct radeon_cs_chunk *relocs_chunk;
    2440             :         unsigned idx;
    2441             : 
    2442           0 :         *cs_reloc = NULL;
    2443           0 :         if (p->chunk_relocs == NULL) {
    2444           0 :                 DRM_ERROR("No relocation chunk !\n");
    2445           0 :                 return -EINVAL;
    2446             :         }
    2447             :         relocs_chunk = p->chunk_relocs;
    2448           0 :         idx = p->dma_reloc_idx;
    2449           0 :         if (idx >= p->nrelocs) {
    2450           0 :                 DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
    2451             :                           idx, p->nrelocs);
    2452           0 :                 return -EINVAL;
    2453             :         }
    2454           0 :         *cs_reloc = &p->relocs[idx];
    2455           0 :         p->dma_reloc_idx++;
    2456           0 :         return 0;
    2457           0 : }
    2458             : 
    2459             : #define GET_DMA_CMD(h) (((h) & 0xf0000000) >> 28)
    2460             : #define GET_DMA_COUNT(h) ((h) & 0x0000ffff)
    2461             : #define GET_DMA_T(h) (((h) & 0x00800000) >> 23)
    2462             : 
    2463             : /**
    2464             :  * r600_dma_cs_parse() - parse the DMA IB
    2465             :  * @p:          parser structure holding parsing context.
    2466             :  *
    2467             :  * Parses the DMA IB from the CS ioctl and updates
    2468             :  * the GPU addresses based on the reloc information and
    2469             :  * checks for errors. (R6xx-R7xx)
    2470             :  * Returns 0 for success and an error on failure.
    2471             :  **/
    2472           0 : int r600_dma_cs_parse(struct radeon_cs_parser *p)
    2473             : {
    2474           0 :         struct radeon_cs_chunk *ib_chunk = p->chunk_ib;
    2475           0 :         struct radeon_bo_list *src_reloc, *dst_reloc;
    2476             :         u32 header, cmd, count, tiled;
    2477           0 :         volatile u32 *ib = p->ib.ptr;
    2478             :         u32 idx, idx_value;
    2479             :         u64 src_offset, dst_offset;
    2480             :         int r;
    2481             : 
    2482           0 :         do {
    2483           0 :                 if (p->idx >= ib_chunk->length_dw) {
    2484           0 :                         DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
    2485             :                                   p->idx, ib_chunk->length_dw);
    2486           0 :                         return -EINVAL;
    2487             :                 }
    2488             :                 idx = p->idx;
    2489           0 :                 header = radeon_get_ib_value(p, idx);
    2490           0 :                 cmd = GET_DMA_CMD(header);
    2491           0 :                 count = GET_DMA_COUNT(header);
    2492           0 :                 tiled = GET_DMA_T(header);
    2493             : 
    2494           0 :                 switch (cmd) {
    2495             :                 case DMA_PACKET_WRITE:
    2496           0 :                         r = r600_dma_cs_next_reloc(p, &dst_reloc);
    2497           0 :                         if (r) {
    2498           0 :                                 DRM_ERROR("bad DMA_PACKET_WRITE\n");
    2499           0 :                                 return -EINVAL;
    2500             :                         }
    2501           0 :                         if (tiled) {
    2502             :                                 dst_offset = radeon_get_ib_value(p, idx+1);
    2503           0 :                                 dst_offset <<= 8;
    2504             : 
    2505           0 :                                 ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8);
    2506           0 :                                 p->idx += count + 5;
    2507           0 :                         } else {
    2508             :                                 dst_offset = radeon_get_ib_value(p, idx+1);
    2509           0 :                                 dst_offset |= ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
    2510             : 
    2511           0 :                                 ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
    2512           0 :                                 ib[idx+2] += upper_32_bits(dst_reloc->gpu_offset) & 0xff;
    2513           0 :                                 p->idx += count + 3;
    2514             :                         }
    2515           0 :                         if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
    2516           0 :                                 dev_warn(p->dev, "DMA write buffer too small (%llu %lu)\n",
    2517             :                                          dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
    2518           0 :                                 return -EINVAL;
    2519             :                         }
    2520             :                         break;
    2521             :                 case DMA_PACKET_COPY:
    2522           0 :                         r = r600_dma_cs_next_reloc(p, &src_reloc);
    2523           0 :                         if (r) {
    2524           0 :                                 DRM_ERROR("bad DMA_PACKET_COPY\n");
    2525           0 :                                 return -EINVAL;
    2526             :                         }
    2527           0 :                         r = r600_dma_cs_next_reloc(p, &dst_reloc);
    2528           0 :                         if (r) {
    2529           0 :                                 DRM_ERROR("bad DMA_PACKET_COPY\n");
    2530           0 :                                 return -EINVAL;
    2531             :                         }
    2532           0 :                         if (tiled) {
    2533           0 :                                 idx_value = radeon_get_ib_value(p, idx + 2);
    2534             :                                 /* detile bit */
    2535           0 :                                 if (idx_value & (1 << 31)) {
    2536             :                                         /* tiled src, linear dst */
    2537           0 :                                         src_offset = radeon_get_ib_value(p, idx+1);
    2538           0 :                                         src_offset <<= 8;
    2539           0 :                                         ib[idx+1] += (u32)(src_reloc->gpu_offset >> 8);
    2540             : 
    2541           0 :                                         dst_offset = radeon_get_ib_value(p, idx+5);
    2542           0 :                                         dst_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32;
    2543           0 :                                         ib[idx+5] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
    2544           0 :                                         ib[idx+6] += upper_32_bits(dst_reloc->gpu_offset) & 0xff;
    2545           0 :                                 } else {
    2546             :                                         /* linear src, tiled dst */
    2547           0 :                                         src_offset = radeon_get_ib_value(p, idx+5);
    2548           0 :                                         src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32;
    2549           0 :                                         ib[idx+5] += (u32)(src_reloc->gpu_offset & 0xfffffffc);
    2550           0 :                                         ib[idx+6] += upper_32_bits(src_reloc->gpu_offset) & 0xff;
    2551             : 
    2552           0 :                                         dst_offset = radeon_get_ib_value(p, idx+1);
    2553           0 :                                         dst_offset <<= 8;
    2554           0 :                                         ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8);
    2555             :                                 }
    2556           0 :                                 p->idx += 7;
    2557           0 :                         } else {
    2558           0 :                                 if (p->family >= CHIP_RV770) {
    2559             :                                         src_offset = radeon_get_ib_value(p, idx+2);
    2560           0 :                                         src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
    2561           0 :                                         dst_offset = radeon_get_ib_value(p, idx+1);
    2562           0 :                                         dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
    2563             : 
    2564           0 :                                         ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
    2565           0 :                                         ib[idx+2] += (u32)(src_reloc->gpu_offset & 0xfffffffc);
    2566           0 :                                         ib[idx+3] += upper_32_bits(dst_reloc->gpu_offset) & 0xff;
    2567           0 :                                         ib[idx+4] += upper_32_bits(src_reloc->gpu_offset) & 0xff;
    2568           0 :                                         p->idx += 5;
    2569           0 :                                 } else {
    2570             :                                         src_offset = radeon_get_ib_value(p, idx+2);
    2571           0 :                                         src_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
    2572           0 :                                         dst_offset = radeon_get_ib_value(p, idx+1);
    2573           0 :                                         dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff0000)) << 16;
    2574             : 
    2575           0 :                                         ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
    2576           0 :                                         ib[idx+2] += (u32)(src_reloc->gpu_offset & 0xfffffffc);
    2577           0 :                                         ib[idx+3] += upper_32_bits(src_reloc->gpu_offset) & 0xff;
    2578           0 :                                         ib[idx+3] += (upper_32_bits(dst_reloc->gpu_offset) & 0xff) << 16;
    2579           0 :                                         p->idx += 4;
    2580             :                                 }
    2581             :                         }
    2582           0 :                         if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
    2583           0 :                                 dev_warn(p->dev, "DMA copy src buffer too small (%llu %lu)\n",
    2584             :                                          src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
    2585           0 :                                 return -EINVAL;
    2586             :                         }
    2587           0 :                         if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
    2588           0 :                                 dev_warn(p->dev, "DMA write dst buffer too small (%llu %lu)\n",
    2589             :                                          dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
    2590           0 :                                 return -EINVAL;
    2591             :                         }
    2592             :                         break;
    2593             :                 case DMA_PACKET_CONSTANT_FILL:
    2594           0 :                         if (p->family < CHIP_RV770) {
    2595           0 :                                 DRM_ERROR("Constant Fill is 7xx only !\n");
    2596           0 :                                 return -EINVAL;
    2597             :                         }
    2598           0 :                         r = r600_dma_cs_next_reloc(p, &dst_reloc);
    2599           0 :                         if (r) {
    2600           0 :                                 DRM_ERROR("bad DMA_PACKET_WRITE\n");
    2601           0 :                                 return -EINVAL;
    2602             :                         }
    2603           0 :                         dst_offset = radeon_get_ib_value(p, idx+1);
    2604           0 :                         dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0x00ff0000)) << 16;
    2605           0 :                         if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
    2606           0 :                                 dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n",
    2607             :                                          dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
    2608           0 :                                 return -EINVAL;
    2609             :                         }
    2610           0 :                         ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
    2611           0 :                         ib[idx+3] += (upper_32_bits(dst_reloc->gpu_offset) << 16) & 0x00ff0000;
    2612           0 :                         p->idx += 4;
    2613           0 :                         break;
    2614             :                 case DMA_PACKET_NOP:
    2615           0 :                         p->idx += 1;
    2616           0 :                         break;
    2617             :                 default:
    2618           0 :                         DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx);
    2619           0 :                         return -EINVAL;
    2620             :                 }
    2621           0 :         } while (p->idx < p->chunk_ib->length_dw);
    2622             : #if 0
    2623             :         for (r = 0; r < p->ib->length_dw; r++) {
    2624             :                 printk(KERN_INFO "%05d  0x%08X\n", r, p->ib.ptr[r]);
    2625             :                 mdelay(1);
    2626             :         }
    2627             : #endif
    2628           0 :         return 0;
    2629           0 : }

Generated by: LCOV version 1.13