aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2012-12-13 09:55:45 -0500
committerAlex Deucher <alexander.deucher@amd.com>2012-12-14 10:45:25 -0500
commitd2ead3eaf8a4bf92129eda69189ce18a6c1cc8bd (patch)
tree61502ccac6c09b16184b617bfdcb309d19114ccf /drivers/gpu/drm/radeon
parentcf4ccd016bae1a03bb38170eb54b5db4b04e0545 (diff)
drm/radeon/kms: add evergreen/cayman CS parser for async DMA (v2)
Allows us to use the DMA ring from userspace. DMA doesn't have a good NOP packet in which to embed the reloc idx, so userspace has to add a reloc for each buffer used and order them to match the command stream. v2: fix address bounds checking Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon')
-rw-r--r--drivers/gpu/drm/radeon/evergreen_cs.c451
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c14
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h1
3 files changed, 459 insertions, 7 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
index fc7e613124d..0a1ec4e6f15 100644
--- a/drivers/gpu/drm/radeon/evergreen_cs.c
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -34,6 +34,8 @@
34#define MAX(a,b) (((a)>(b))?(a):(b)) 34#define MAX(a,b) (((a)>(b))?(a):(b))
35#define MIN(a,b) (((a)<(b))?(a):(b)) 35#define MIN(a,b) (((a)<(b))?(a):(b))
36 36
37int r600_dma_cs_next_reloc(struct radeon_cs_parser *p,
38 struct radeon_cs_reloc **cs_reloc);
37static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p, 39static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
38 struct radeon_cs_reloc **cs_reloc); 40 struct radeon_cs_reloc **cs_reloc);
39 41
@@ -2815,6 +2817,455 @@ int evergreen_cs_parse(struct radeon_cs_parser *p)
2815 return 0; 2817 return 0;
2816} 2818}
2817 2819
2820/*
2821 * DMA
2822 */
2823
2824#define GET_DMA_CMD(h) (((h) & 0xf0000000) >> 28)
2825#define GET_DMA_COUNT(h) ((h) & 0x000fffff)
2826#define GET_DMA_T(h) (((h) & 0x00800000) >> 23)
2827#define GET_DMA_NEW(h) (((h) & 0x04000000) >> 26)
2828#define GET_DMA_MISC(h) (((h) & 0x0700000) >> 20)
2829
2830/**
2831 * evergreen_dma_cs_parse() - parse the DMA IB
2832 * @p: parser structure holding parsing context.
2833 *
2834 * Parses the DMA IB from the CS ioctl and updates
2835 * the GPU addresses based on the reloc information and
2836 * checks for errors. (Evergreen-Cayman)
2837 * Returns 0 for success and an error on failure.
2838 **/
2839int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
2840{
2841 struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
2842 struct radeon_cs_reloc *src_reloc, *dst_reloc, *dst2_reloc;
2843 u32 header, cmd, count, tiled, new_cmd, misc;
2844 volatile u32 *ib = p->ib.ptr;
2845 u32 idx, idx_value;
2846 u64 src_offset, dst_offset, dst2_offset;
2847 int r;
2848
2849 do {
2850 if (p->idx >= ib_chunk->length_dw) {
2851 DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
2852 p->idx, ib_chunk->length_dw);
2853 return -EINVAL;
2854 }
2855 idx = p->idx;
2856 header = radeon_get_ib_value(p, idx);
2857 cmd = GET_DMA_CMD(header);
2858 count = GET_DMA_COUNT(header);
2859 tiled = GET_DMA_T(header);
2860 new_cmd = GET_DMA_NEW(header);
2861 misc = GET_DMA_MISC(header);
2862
2863 switch (cmd) {
2864 case DMA_PACKET_WRITE:
2865 r = r600_dma_cs_next_reloc(p, &dst_reloc);
2866 if (r) {
2867 DRM_ERROR("bad DMA_PACKET_WRITE\n");
2868 return -EINVAL;
2869 }
2870 if (tiled) {
2871 dst_offset = ib[idx+1];
2872 dst_offset <<= 8;
2873
2874 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
2875 p->idx += count + 7;
2876 } else {
2877 dst_offset = ib[idx+1];
2878 dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32;
2879
2880 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
2881 ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
2882 p->idx += count + 3;
2883 }
2884 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
2885 dev_warn(p->dev, "DMA write buffer too small (%llu %lu)\n",
2886 dst_offset, radeon_bo_size(dst_reloc->robj));
2887 return -EINVAL;
2888 }
2889 break;
2890 case DMA_PACKET_COPY:
2891 r = r600_dma_cs_next_reloc(p, &src_reloc);
2892 if (r) {
2893 DRM_ERROR("bad DMA_PACKET_COPY\n");
2894 return -EINVAL;
2895 }
2896 r = r600_dma_cs_next_reloc(p, &dst_reloc);
2897 if (r) {
2898 DRM_ERROR("bad DMA_PACKET_COPY\n");
2899 return -EINVAL;
2900 }
2901 if (tiled) {
2902 idx_value = radeon_get_ib_value(p, idx + 2);
2903 if (new_cmd) {
2904 switch (misc) {
2905 case 0:
2906 /* L2T, frame to fields */
2907 if (idx_value & (1 << 31)) {
2908 DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
2909 return -EINVAL;
2910 }
2911 r = r600_dma_cs_next_reloc(p, &dst2_reloc);
2912 if (r) {
2913 DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
2914 return -EINVAL;
2915 }
2916 dst_offset = ib[idx+1];
2917 dst_offset <<= 8;
2918 dst2_offset = ib[idx+2];
2919 dst2_offset <<= 8;
2920 src_offset = ib[idx+8];
2921 src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
2922 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
2923 dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%llu %lu)\n",
2924 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
2925 return -EINVAL;
2926 }
2927 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
2928 dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n",
2929 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
2930 return -EINVAL;
2931 }
2932 if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
2933 dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n",
2934 dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
2935 return -EINVAL;
2936 }
2937 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
2938 ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
2939 ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
2940 ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
2941 p->idx += 10;
2942 break;
2943 case 1:
2944 /* L2T, T2L partial */
2945 if (p->family < CHIP_CAYMAN) {
2946 DRM_ERROR("L2T, T2L Partial is cayman only !\n");
2947 return -EINVAL;
2948 }
2949 /* detile bit */
2950 if (idx_value & (1 << 31)) {
2951 /* tiled src, linear dst */
2952 ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
2953
2954 ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
2955 ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
2956 } else {
2957 /* linear src, tiled dst */
2958 ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
2959 ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
2960
2961 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
2962 }
2963 p->idx += 12;
2964 break;
2965 case 3:
2966 /* L2T, broadcast */
2967 if (idx_value & (1 << 31)) {
2968 DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
2969 return -EINVAL;
2970 }
2971 r = r600_dma_cs_next_reloc(p, &dst2_reloc);
2972 if (r) {
2973 DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
2974 return -EINVAL;
2975 }
2976 dst_offset = ib[idx+1];
2977 dst_offset <<= 8;
2978 dst2_offset = ib[idx+2];
2979 dst2_offset <<= 8;
2980 src_offset = ib[idx+8];
2981 src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
2982 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
2983 dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
2984 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
2985 return -EINVAL;
2986 }
2987 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
2988 dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
2989 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
2990 return -EINVAL;
2991 }
2992 if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
2993 dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n",
2994 dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
2995 return -EINVAL;
2996 }
2997 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
2998 ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
2999 ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
3000 ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3001 p->idx += 10;
3002 break;
3003 case 4:
3004 /* L2T, T2L */
3005 /* detile bit */
3006 if (idx_value & (1 << 31)) {
3007 /* tiled src, linear dst */
3008 src_offset = ib[idx+1];
3009 src_offset <<= 8;
3010 ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
3011
3012 dst_offset = ib[idx+7];
3013 dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
3014 ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
3015 ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3016 } else {
3017 /* linear src, tiled dst */
3018 src_offset = ib[idx+7];
3019 src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
3020 ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
3021 ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3022
3023 dst_offset = ib[idx+1];
3024 dst_offset <<= 8;
3025 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
3026 }
3027 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
3028 dev_warn(p->dev, "DMA L2T, T2L src buffer too small (%llu %lu)\n",
3029 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
3030 return -EINVAL;
3031 }
3032 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3033 dev_warn(p->dev, "DMA L2T, T2L dst buffer too small (%llu %lu)\n",
3034 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
3035 return -EINVAL;
3036 }
3037 p->idx += 9;
3038 break;
3039 case 5:
3040 /* T2T partial */
3041 if (p->family < CHIP_CAYMAN) {
3042 DRM_ERROR("L2T, T2L Partial is cayman only !\n");
3043 return -EINVAL;
3044 }
3045 ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
3046 ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
3047 p->idx += 13;
3048 break;
3049 case 7:
3050 /* L2T, broadcast */
3051 if (idx_value & (1 << 31)) {
3052 DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
3053 return -EINVAL;
3054 }
3055 r = r600_dma_cs_next_reloc(p, &dst2_reloc);
3056 if (r) {
3057 DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
3058 return -EINVAL;
3059 }
3060 dst_offset = ib[idx+1];
3061 dst_offset <<= 8;
3062 dst2_offset = ib[idx+2];
3063 dst2_offset <<= 8;
3064 src_offset = ib[idx+8];
3065 src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
3066 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
3067 dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
3068 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
3069 return -EINVAL;
3070 }
3071 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3072 dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
3073 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
3074 return -EINVAL;
3075 }
3076 if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
3077 dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n",
3078 dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
3079 return -EINVAL;
3080 }
3081 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
3082 ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
3083 ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
3084 ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3085 p->idx += 10;
3086 break;
3087 default:
3088 DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
3089 return -EINVAL;
3090 }
3091 } else {
3092 switch (misc) {
3093 case 0:
3094 /* detile bit */
3095 if (idx_value & (1 << 31)) {
3096 /* tiled src, linear dst */
3097 src_offset = ib[idx+1];
3098 src_offset <<= 8;
3099 ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
3100
3101 dst_offset = ib[idx+7];
3102 dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
3103 ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
3104 ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3105 } else {
3106 /* linear src, tiled dst */
3107 src_offset = ib[idx+7];
3108 src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
3109 ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
3110 ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3111
3112 dst_offset = ib[idx+1];
3113 dst_offset <<= 8;
3114 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
3115 }
3116 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
3117 dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
3118 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
3119 return -EINVAL;
3120 }
3121 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3122 dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
3123 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
3124 return -EINVAL;
3125 }
3126 p->idx += 9;
3127 break;
3128 default:
3129 DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
3130 return -EINVAL;
3131 }
3132 }
3133 } else {
3134 if (new_cmd) {
3135 switch (misc) {
3136 case 0:
3137 /* L2L, byte */
3138 src_offset = ib[idx+2];
3139 src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
3140 dst_offset = ib[idx+1];
3141 dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
3142 if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) {
3143 dev_warn(p->dev, "DMA L2L, byte src buffer too small (%llu %lu)\n",
3144 src_offset + count, radeon_bo_size(src_reloc->robj));
3145 return -EINVAL;
3146 }
3147 if ((dst_offset + count) > radeon_bo_size(dst_reloc->robj)) {
3148 dev_warn(p->dev, "DMA L2L, byte dst buffer too small (%llu %lu)\n",
3149 dst_offset + count, radeon_bo_size(dst_reloc->robj));
3150 return -EINVAL;
3151 }
3152 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff);
3153 ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff);
3154 ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3155 ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3156 p->idx += 5;
3157 break;
3158 case 1:
3159 /* L2L, partial */
3160 if (p->family < CHIP_CAYMAN) {
3161 DRM_ERROR("L2L Partial is cayman only !\n");
3162 return -EINVAL;
3163 }
3164 ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff);
3165 ib[idx+2] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3166 ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff);
3167 ib[idx+5] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3168
3169 p->idx += 9;
3170 break;
3171 case 4:
3172 /* L2L, dw, broadcast */
3173 r = r600_dma_cs_next_reloc(p, &dst2_reloc);
3174 if (r) {
3175 DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n");
3176 return -EINVAL;
3177 }
3178 dst_offset = ib[idx+1];
3179 dst_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
3180 dst2_offset = ib[idx+2];
3181 dst2_offset |= ((u64)(ib[idx+5] & 0xff)) << 32;
3182 src_offset = ib[idx+3];
3183 src_offset |= ((u64)(ib[idx+6] & 0xff)) << 32;
3184 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
3185 dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%llu %lu)\n",
3186 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
3187 return -EINVAL;
3188 }
3189 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3190 dev_warn(p->dev, "DMA L2L, dw, broadcast dst buffer too small (%llu %lu)\n",
3191 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
3192 return -EINVAL;
3193 }
3194 if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
3195 dev_warn(p->dev, "DMA L2L, dw, broadcast dst2 buffer too small (%llu %lu)\n",
3196 dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
3197 return -EINVAL;
3198 }
3199 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
3200 ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset & 0xfffffffc);
3201 ib[idx+3] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
3202 ib[idx+4] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3203 ib[idx+5] += upper_32_bits(dst2_reloc->lobj.gpu_offset) & 0xff;
3204 ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3205 p->idx += 7;
3206 break;
3207 default:
3208 DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
3209 return -EINVAL;
3210 }
3211 } else {
3212 /* L2L, dw */
3213 src_offset = ib[idx+2];
3214 src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
3215 dst_offset = ib[idx+1];
3216 dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
3217 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
3218 dev_warn(p->dev, "DMA L2L, dw src buffer too small (%llu %lu)\n",
3219 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
3220 return -EINVAL;
3221 }
3222 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3223 dev_warn(p->dev, "DMA L2L, dw dst buffer too small (%llu %lu)\n",
3224 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
3225 return -EINVAL;
3226 }
3227 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
3228 ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
3229 ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3230 ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3231 p->idx += 5;
3232 }
3233 }
3234 break;
3235 case DMA_PACKET_CONSTANT_FILL:
3236 r = r600_dma_cs_next_reloc(p, &dst_reloc);
3237 if (r) {
3238 DRM_ERROR("bad DMA_PACKET_CONSTANT_FILL\n");
3239 return -EINVAL;
3240 }
3241 dst_offset = ib[idx+1];
3242 dst_offset |= ((u64)(ib[idx+3] & 0x00ff0000)) << 16;
3243 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3244 dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n",
3245 dst_offset, radeon_bo_size(dst_reloc->robj));
3246 return -EINVAL;
3247 }
3248 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
3249 ib[idx+3] += (upper_32_bits(dst_reloc->lobj.gpu_offset) << 16) & 0x00ff0000;
3250 p->idx += 4;
3251 break;
3252 case DMA_PACKET_NOP:
3253 p->idx += 1;
3254 break;
3255 default:
3256 DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx);
3257 return -EINVAL;
3258 }
3259 } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
3260#if 0
3261 for (r = 0; r < p->ib->length_dw; r++) {
3262 printk(KERN_INFO "%05d 0x%08X\n", r, p->ib.ptr[r]);
3263 mdelay(1);
3264 }
3265#endif
3266 return 0;
3267}
3268
2818/* vm parser */ 3269/* vm parser */
2819static bool evergreen_vm_reg_valid(u32 reg) 3270static bool evergreen_vm_reg_valid(u32 reg)
2820{ 3271{
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index d3603417e5d..ac1d5702144 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -1204,7 +1204,7 @@ static struct radeon_asic evergreen_asic = {
1204 .ib_execute = &evergreen_dma_ring_ib_execute, 1204 .ib_execute = &evergreen_dma_ring_ib_execute,
1205 .emit_fence = &evergreen_dma_fence_ring_emit, 1205 .emit_fence = &evergreen_dma_fence_ring_emit,
1206 .emit_semaphore = &r600_dma_semaphore_ring_emit, 1206 .emit_semaphore = &r600_dma_semaphore_ring_emit,
1207 .cs_parse = NULL, 1207 .cs_parse = &evergreen_dma_cs_parse,
1208 .ring_test = &r600_dma_ring_test, 1208 .ring_test = &r600_dma_ring_test,
1209 .ib_test = &r600_dma_ib_test, 1209 .ib_test = &r600_dma_ib_test,
1210 .is_lockup = &r600_dma_is_lockup, 1210 .is_lockup = &r600_dma_is_lockup,
@@ -1288,7 +1288,7 @@ static struct radeon_asic sumo_asic = {
1288 .ib_execute = &evergreen_dma_ring_ib_execute, 1288 .ib_execute = &evergreen_dma_ring_ib_execute,
1289 .emit_fence = &evergreen_dma_fence_ring_emit, 1289 .emit_fence = &evergreen_dma_fence_ring_emit,
1290 .emit_semaphore = &r600_dma_semaphore_ring_emit, 1290 .emit_semaphore = &r600_dma_semaphore_ring_emit,
1291 .cs_parse = NULL, 1291 .cs_parse = &evergreen_dma_cs_parse,
1292 .ring_test = &r600_dma_ring_test, 1292 .ring_test = &r600_dma_ring_test,
1293 .ib_test = &r600_dma_ib_test, 1293 .ib_test = &r600_dma_ib_test,
1294 .is_lockup = &r600_dma_is_lockup, 1294 .is_lockup = &r600_dma_is_lockup,
@@ -1372,7 +1372,7 @@ static struct radeon_asic btc_asic = {
1372 .ib_execute = &evergreen_dma_ring_ib_execute, 1372 .ib_execute = &evergreen_dma_ring_ib_execute,
1373 .emit_fence = &evergreen_dma_fence_ring_emit, 1373 .emit_fence = &evergreen_dma_fence_ring_emit,
1374 .emit_semaphore = &r600_dma_semaphore_ring_emit, 1374 .emit_semaphore = &r600_dma_semaphore_ring_emit,
1375 .cs_parse = NULL, 1375 .cs_parse = &evergreen_dma_cs_parse,
1376 .ring_test = &r600_dma_ring_test, 1376 .ring_test = &r600_dma_ring_test,
1377 .ib_test = &r600_dma_ib_test, 1377 .ib_test = &r600_dma_ib_test,
1378 .is_lockup = &r600_dma_is_lockup, 1378 .is_lockup = &r600_dma_is_lockup,
@@ -1486,7 +1486,7 @@ static struct radeon_asic cayman_asic = {
1486 .ib_execute = &cayman_dma_ring_ib_execute, 1486 .ib_execute = &cayman_dma_ring_ib_execute,
1487 .emit_fence = &evergreen_dma_fence_ring_emit, 1487 .emit_fence = &evergreen_dma_fence_ring_emit,
1488 .emit_semaphore = &r600_dma_semaphore_ring_emit, 1488 .emit_semaphore = &r600_dma_semaphore_ring_emit,
1489 .cs_parse = NULL, 1489 .cs_parse = &evergreen_dma_cs_parse,
1490 .ring_test = &r600_dma_ring_test, 1490 .ring_test = &r600_dma_ring_test,
1491 .ib_test = &r600_dma_ib_test, 1491 .ib_test = &r600_dma_ib_test,
1492 .is_lockup = &cayman_dma_is_lockup, 1492 .is_lockup = &cayman_dma_is_lockup,
@@ -1496,7 +1496,7 @@ static struct radeon_asic cayman_asic = {
1496 .ib_execute = &cayman_dma_ring_ib_execute, 1496 .ib_execute = &cayman_dma_ring_ib_execute,
1497 .emit_fence = &evergreen_dma_fence_ring_emit, 1497 .emit_fence = &evergreen_dma_fence_ring_emit,
1498 .emit_semaphore = &r600_dma_semaphore_ring_emit, 1498 .emit_semaphore = &r600_dma_semaphore_ring_emit,
1499 .cs_parse = NULL, 1499 .cs_parse = &evergreen_dma_cs_parse,
1500 .ring_test = &r600_dma_ring_test, 1500 .ring_test = &r600_dma_ring_test,
1501 .ib_test = &r600_dma_ib_test, 1501 .ib_test = &r600_dma_ib_test,
1502 .is_lockup = &cayman_dma_is_lockup, 1502 .is_lockup = &cayman_dma_is_lockup,
@@ -1611,7 +1611,7 @@ static struct radeon_asic trinity_asic = {
1611 .ib_execute = &cayman_dma_ring_ib_execute, 1611 .ib_execute = &cayman_dma_ring_ib_execute,
1612 .emit_fence = &evergreen_dma_fence_ring_emit, 1612 .emit_fence = &evergreen_dma_fence_ring_emit,
1613 .emit_semaphore = &r600_dma_semaphore_ring_emit, 1613 .emit_semaphore = &r600_dma_semaphore_ring_emit,
1614 .cs_parse = NULL, 1614 .cs_parse = &evergreen_dma_cs_parse,
1615 .ring_test = &r600_dma_ring_test, 1615 .ring_test = &r600_dma_ring_test,
1616 .ib_test = &r600_dma_ib_test, 1616 .ib_test = &r600_dma_ib_test,
1617 .is_lockup = &cayman_dma_is_lockup, 1617 .is_lockup = &cayman_dma_is_lockup,
@@ -1621,7 +1621,7 @@ static struct radeon_asic trinity_asic = {
1621 .ib_execute = &cayman_dma_ring_ib_execute, 1621 .ib_execute = &cayman_dma_ring_ib_execute,
1622 .emit_fence = &evergreen_dma_fence_ring_emit, 1622 .emit_fence = &evergreen_dma_fence_ring_emit,
1623 .emit_semaphore = &r600_dma_semaphore_ring_emit, 1623 .emit_semaphore = &r600_dma_semaphore_ring_emit,
1624 .cs_parse = NULL, 1624 .cs_parse = &evergreen_dma_cs_parse,
1625 .ring_test = &r600_dma_ring_test, 1625 .ring_test = &r600_dma_ring_test,
1626 .ib_test = &r600_dma_ib_test, 1626 .ib_test = &r600_dma_ib_test,
1627 .is_lockup = &cayman_dma_is_lockup, 1627 .is_lockup = &cayman_dma_is_lockup,
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index b311c0a2ec6..d2ac64619f3 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -431,6 +431,7 @@ u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc);
431int evergreen_irq_set(struct radeon_device *rdev); 431int evergreen_irq_set(struct radeon_device *rdev);
432int evergreen_irq_process(struct radeon_device *rdev); 432int evergreen_irq_process(struct radeon_device *rdev);
433extern int evergreen_cs_parse(struct radeon_cs_parser *p); 433extern int evergreen_cs_parse(struct radeon_cs_parser *p);
434extern int evergreen_dma_cs_parse(struct radeon_cs_parser *p);
434extern void evergreen_pm_misc(struct radeon_device *rdev); 435extern void evergreen_pm_misc(struct radeon_device *rdev);
435extern void evergreen_pm_prepare(struct radeon_device *rdev); 436extern void evergreen_pm_prepare(struct radeon_device *rdev);
436extern void evergreen_pm_finish(struct radeon_device *rdev); 437extern void evergreen_pm_finish(struct radeon_device *rdev);