aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_state.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_state.c208
1 files changed, 112 insertions, 96 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c
index 38537d971a3e..cc5316dcf580 100644
--- a/drivers/gpu/drm/radeon/radeon_state.c
+++ b/drivers/gpu/drm/radeon/radeon_state.c
@@ -29,6 +29,7 @@
29 29
30#include "drmP.h" 30#include "drmP.h"
31#include "drm.h" 31#include "drm.h"
32#include "drm_buffer.h"
32#include "drm_sarea.h" 33#include "drm_sarea.h"
33#include "radeon_drm.h" 34#include "radeon_drm.h"
34#include "radeon_drv.h" 35#include "radeon_drv.h"
@@ -91,21 +92,27 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
91static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * 92static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
92 dev_priv, 93 dev_priv,
93 struct drm_file *file_priv, 94 struct drm_file *file_priv,
94 int id, u32 *data) 95 int id, struct drm_buffer *buf)
95{ 96{
97 u32 *data;
96 switch (id) { 98 switch (id) {
97 99
98 case RADEON_EMIT_PP_MISC: 100 case RADEON_EMIT_PP_MISC:
99 if (radeon_check_and_fixup_offset(dev_priv, file_priv, 101 data = drm_buffer_pointer_to_dword(buf,
100 &data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) { 102 (RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4);
103
104 if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
101 DRM_ERROR("Invalid depth buffer offset\n"); 105 DRM_ERROR("Invalid depth buffer offset\n");
102 return -EINVAL; 106 return -EINVAL;
103 } 107 }
108 dev_priv->have_z_offset = 1;
104 break; 109 break;
105 110
106 case RADEON_EMIT_PP_CNTL: 111 case RADEON_EMIT_PP_CNTL:
107 if (radeon_check_and_fixup_offset(dev_priv, file_priv, 112 data = drm_buffer_pointer_to_dword(buf,
108 &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) { 113 (RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4);
114
115 if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
109 DRM_ERROR("Invalid colour buffer offset\n"); 116 DRM_ERROR("Invalid colour buffer offset\n");
110 return -EINVAL; 117 return -EINVAL;
111 } 118 }
@@ -117,8 +124,8 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
117 case R200_EMIT_PP_TXOFFSET_3: 124 case R200_EMIT_PP_TXOFFSET_3:
118 case R200_EMIT_PP_TXOFFSET_4: 125 case R200_EMIT_PP_TXOFFSET_4:
119 case R200_EMIT_PP_TXOFFSET_5: 126 case R200_EMIT_PP_TXOFFSET_5:
120 if (radeon_check_and_fixup_offset(dev_priv, file_priv, 127 data = drm_buffer_pointer_to_dword(buf, 0);
121 &data[0])) { 128 if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
122 DRM_ERROR("Invalid R200 texture offset\n"); 129 DRM_ERROR("Invalid R200 texture offset\n");
123 return -EINVAL; 130 return -EINVAL;
124 } 131 }
@@ -127,8 +134,9 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
127 case RADEON_EMIT_PP_TXFILTER_0: 134 case RADEON_EMIT_PP_TXFILTER_0:
128 case RADEON_EMIT_PP_TXFILTER_1: 135 case RADEON_EMIT_PP_TXFILTER_1:
129 case RADEON_EMIT_PP_TXFILTER_2: 136 case RADEON_EMIT_PP_TXFILTER_2:
130 if (radeon_check_and_fixup_offset(dev_priv, file_priv, 137 data = drm_buffer_pointer_to_dword(buf,
131 &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) { 138 (RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4);
139 if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
132 DRM_ERROR("Invalid R100 texture offset\n"); 140 DRM_ERROR("Invalid R100 texture offset\n");
133 return -EINVAL; 141 return -EINVAL;
134 } 142 }
@@ -142,9 +150,10 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
142 case R200_EMIT_PP_CUBIC_OFFSETS_5:{ 150 case R200_EMIT_PP_CUBIC_OFFSETS_5:{
143 int i; 151 int i;
144 for (i = 0; i < 5; i++) { 152 for (i = 0; i < 5; i++) {
153 data = drm_buffer_pointer_to_dword(buf, i);
145 if (radeon_check_and_fixup_offset(dev_priv, 154 if (radeon_check_and_fixup_offset(dev_priv,
146 file_priv, 155 file_priv,
147 &data[i])) { 156 data)) {
148 DRM_ERROR 157 DRM_ERROR
149 ("Invalid R200 cubic texture offset\n"); 158 ("Invalid R200 cubic texture offset\n");
150 return -EINVAL; 159 return -EINVAL;
@@ -158,9 +167,10 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
158 case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{ 167 case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{
159 int i; 168 int i;
160 for (i = 0; i < 5; i++) { 169 for (i = 0; i < 5; i++) {
170 data = drm_buffer_pointer_to_dword(buf, i);
161 if (radeon_check_and_fixup_offset(dev_priv, 171 if (radeon_check_and_fixup_offset(dev_priv,
162 file_priv, 172 file_priv,
163 &data[i])) { 173 data)) {
164 DRM_ERROR 174 DRM_ERROR
165 ("Invalid R100 cubic texture offset\n"); 175 ("Invalid R100 cubic texture offset\n");
166 return -EINVAL; 176 return -EINVAL;
@@ -269,23 +279,24 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
269 cmdbuf, 279 cmdbuf,
270 unsigned int *cmdsz) 280 unsigned int *cmdsz)
271{ 281{
272 u32 *cmd = (u32 *) cmdbuf->buf; 282 u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
273 u32 offset, narrays; 283 u32 offset, narrays;
274 int count, i, k; 284 int count, i, k;
275 285
276 *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16); 286 count = ((*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16);
287 *cmdsz = 2 + count;
277 288
278 if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) { 289 if ((*cmd & 0xc0000000) != RADEON_CP_PACKET3) {
279 DRM_ERROR("Not a type 3 packet\n"); 290 DRM_ERROR("Not a type 3 packet\n");
280 return -EINVAL; 291 return -EINVAL;
281 } 292 }
282 293
283 if (4 * *cmdsz > cmdbuf->bufsz) { 294 if (4 * *cmdsz > drm_buffer_unprocessed(cmdbuf->buffer)) {
284 DRM_ERROR("Packet size larger than size of data provided\n"); 295 DRM_ERROR("Packet size larger than size of data provided\n");
285 return -EINVAL; 296 return -EINVAL;
286 } 297 }
287 298
288 switch(cmd[0] & 0xff00) { 299 switch (*cmd & 0xff00) {
289 /* XXX Are there old drivers needing other packets? */ 300 /* XXX Are there old drivers needing other packets? */
290 301
291 case RADEON_3D_DRAW_IMMD: 302 case RADEON_3D_DRAW_IMMD:
@@ -312,7 +323,6 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
312 break; 323 break;
313 324
314 case RADEON_3D_LOAD_VBPNTR: 325 case RADEON_3D_LOAD_VBPNTR:
315 count = (cmd[0] >> 16) & 0x3fff;
316 326
317 if (count > 18) { /* 12 arrays max */ 327 if (count > 18) { /* 12 arrays max */
318 DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", 328 DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
@@ -321,13 +331,16 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
321 } 331 }
322 332
323 /* carefully check packet contents */ 333 /* carefully check packet contents */
324 narrays = cmd[1] & ~0xc000; 334 cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
335
336 narrays = *cmd & ~0xc000;
325 k = 0; 337 k = 0;
326 i = 2; 338 i = 2;
327 while ((k < narrays) && (i < (count + 2))) { 339 while ((k < narrays) && (i < (count + 2))) {
328 i++; /* skip attribute field */ 340 i++; /* skip attribute field */
341 cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
329 if (radeon_check_and_fixup_offset(dev_priv, file_priv, 342 if (radeon_check_and_fixup_offset(dev_priv, file_priv,
330 &cmd[i])) { 343 cmd)) {
331 DRM_ERROR 344 DRM_ERROR
332 ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", 345 ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
333 k, i); 346 k, i);
@@ -338,8 +351,10 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
338 if (k == narrays) 351 if (k == narrays)
339 break; 352 break;
340 /* have one more to process, they come in pairs */ 353 /* have one more to process, they come in pairs */
354 cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
355
341 if (radeon_check_and_fixup_offset(dev_priv, 356 if (radeon_check_and_fixup_offset(dev_priv,
342 file_priv, &cmd[i])) 357 file_priv, cmd))
343 { 358 {
344 DRM_ERROR 359 DRM_ERROR
345 ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", 360 ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
@@ -363,7 +378,9 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
363 DRM_ERROR("Invalid 3d packet for r200-class chip\n"); 378 DRM_ERROR("Invalid 3d packet for r200-class chip\n");
364 return -EINVAL; 379 return -EINVAL;
365 } 380 }
366 if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[1])) { 381
382 cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
383 if (radeon_check_and_fixup_offset(dev_priv, file_priv, cmd)) {
367 DRM_ERROR("Invalid rndr_gen_indx offset\n"); 384 DRM_ERROR("Invalid rndr_gen_indx offset\n");
368 return -EINVAL; 385 return -EINVAL;
369 } 386 }
@@ -374,12 +391,15 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
374 DRM_ERROR("Invalid 3d packet for r100-class chip\n"); 391 DRM_ERROR("Invalid 3d packet for r100-class chip\n");
375 return -EINVAL; 392 return -EINVAL;
376 } 393 }
377 if ((cmd[1] & 0x8000ffff) != 0x80000810) { 394
378 DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); 395 cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
396 if ((*cmd & 0x8000ffff) != 0x80000810) {
397 DRM_ERROR("Invalid indx_buffer reg address %08X\n", *cmd);
379 return -EINVAL; 398 return -EINVAL;
380 } 399 }
381 if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[2])) { 400 cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
382 DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); 401 if (radeon_check_and_fixup_offset(dev_priv, file_priv, cmd)) {
402 DRM_ERROR("Invalid indx_buffer offset is %08X\n", *cmd);
383 return -EINVAL; 403 return -EINVAL;
384 } 404 }
385 break; 405 break;
@@ -388,31 +408,34 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
388 case RADEON_CNTL_PAINT_MULTI: 408 case RADEON_CNTL_PAINT_MULTI:
389 case RADEON_CNTL_BITBLT_MULTI: 409 case RADEON_CNTL_BITBLT_MULTI:
390 /* MSB of opcode: next DWORD GUI_CNTL */ 410 /* MSB of opcode: next DWORD GUI_CNTL */
391 if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL 411 cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
412 if (*cmd & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
392 | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { 413 | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
393 offset = cmd[2] << 10; 414 u32 *cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
415 offset = *cmd2 << 10;
394 if (radeon_check_and_fixup_offset 416 if (radeon_check_and_fixup_offset
395 (dev_priv, file_priv, &offset)) { 417 (dev_priv, file_priv, &offset)) {
396 DRM_ERROR("Invalid first packet offset\n"); 418 DRM_ERROR("Invalid first packet offset\n");
397 return -EINVAL; 419 return -EINVAL;
398 } 420 }
399 cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10; 421 *cmd2 = (*cmd2 & 0xffc00000) | offset >> 10;
400 } 422 }
401 423
402 if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) && 424 if ((*cmd & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
403 (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { 425 (*cmd & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
404 offset = cmd[3] << 10; 426 u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3);
427 offset = *cmd3 << 10;
405 if (radeon_check_and_fixup_offset 428 if (radeon_check_and_fixup_offset
406 (dev_priv, file_priv, &offset)) { 429 (dev_priv, file_priv, &offset)) {
407 DRM_ERROR("Invalid second packet offset\n"); 430 DRM_ERROR("Invalid second packet offset\n");
408 return -EINVAL; 431 return -EINVAL;
409 } 432 }
410 cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10; 433 *cmd3 = (*cmd3 & 0xffc00000) | offset >> 10;
411 } 434 }
412 break; 435 break;
413 436
414 default: 437 default:
415 DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00); 438 DRM_ERROR("Invalid packet type %x\n", *cmd & 0xff00);
416 return -EINVAL; 439 return -EINVAL;
417 } 440 }
418 441
@@ -876,6 +899,11 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
876 if (tmp & RADEON_BACK) 899 if (tmp & RADEON_BACK)
877 flags |= RADEON_FRONT; 900 flags |= RADEON_FRONT;
878 } 901 }
902 if (flags & (RADEON_DEPTH|RADEON_STENCIL)) {
903 if (!dev_priv->have_z_offset)
904 printk_once(KERN_ERR "radeon: illegal depth clear request. Buggy mesa detected - please update.\n");
905 flags &= ~(RADEON_DEPTH | RADEON_STENCIL);
906 }
879 907
880 if (flags & (RADEON_FRONT | RADEON_BACK)) { 908 if (flags & (RADEON_FRONT | RADEON_BACK)) {
881 909
@@ -1065,7 +1093,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
1065 /* judging by the first tile offset needed, could possibly 1093 /* judging by the first tile offset needed, could possibly
1066 directly address/clear 4x4 tiles instead of 8x2 * 4x4 1094 directly address/clear 4x4 tiles instead of 8x2 * 4x4
1067 macro tiles, though would still need clear mask for 1095 macro tiles, though would still need clear mask for
1068 right/bottom if truely 4x4 granularity is desired ? */ 1096 right/bottom if truly 4x4 granularity is desired ? */
1069 OUT_RING(tileoffset * 16); 1097 OUT_RING(tileoffset * 16);
1070 /* the number of tiles to clear */ 1098 /* the number of tiles to clear */
1071 OUT_RING(nrtilesx + 1); 1099 OUT_RING(nrtilesx + 1);
@@ -1950,7 +1978,7 @@ static void radeon_apply_surface_regs(int surf_index,
1950 * Note that refcount can be at most 2, since during a free refcount=3 1978 * Note that refcount can be at most 2, since during a free refcount=3
1951 * might mean we have to allocate a new surface which might not always 1979 * might mean we have to allocate a new surface which might not always
1952 * be available. 1980 * be available.
1953 * For example : we allocate three contigous surfaces ABC. If B is 1981 * For example : we allocate three contiguous surfaces ABC. If B is
1954 * freed, we suddenly need two surfaces to store A and C, which might 1982 * freed, we suddenly need two surfaces to store A and C, which might
1955 * not always be available. 1983 * not always be available.
1956 */ 1984 */
@@ -2611,7 +2639,6 @@ static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
2611{ 2639{
2612 int id = (int)header.packet.packet_id; 2640 int id = (int)header.packet.packet_id;
2613 int sz, reg; 2641 int sz, reg;
2614 int *data = (int *)cmdbuf->buf;
2615 RING_LOCALS; 2642 RING_LOCALS;
2616 2643
2617 if (id >= RADEON_MAX_STATE_PACKETS) 2644 if (id >= RADEON_MAX_STATE_PACKETS)
@@ -2620,23 +2647,22 @@ static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
2620 sz = packet[id].len; 2647 sz = packet[id].len;
2621 reg = packet[id].start; 2648 reg = packet[id].start;
2622 2649
2623 if (sz * sizeof(int) > cmdbuf->bufsz) { 2650 if (sz * sizeof(u32) > drm_buffer_unprocessed(cmdbuf->buffer)) {
2624 DRM_ERROR("Packet size provided larger than data provided\n"); 2651 DRM_ERROR("Packet size provided larger than data provided\n");
2625 return -EINVAL; 2652 return -EINVAL;
2626 } 2653 }
2627 2654
2628 if (radeon_check_and_fixup_packets(dev_priv, file_priv, id, data)) { 2655 if (radeon_check_and_fixup_packets(dev_priv, file_priv, id,
2656 cmdbuf->buffer)) {
2629 DRM_ERROR("Packet verification failed\n"); 2657 DRM_ERROR("Packet verification failed\n");
2630 return -EINVAL; 2658 return -EINVAL;
2631 } 2659 }
2632 2660
2633 BEGIN_RING(sz + 1); 2661 BEGIN_RING(sz + 1);
2634 OUT_RING(CP_PACKET0(reg, (sz - 1))); 2662 OUT_RING(CP_PACKET0(reg, (sz - 1)));
2635 OUT_RING_TABLE(data, sz); 2663 OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
2636 ADVANCE_RING(); 2664 ADVANCE_RING();
2637 2665
2638 cmdbuf->buf += sz * sizeof(int);
2639 cmdbuf->bufsz -= sz * sizeof(int);
2640 return 0; 2666 return 0;
2641} 2667}
2642 2668
@@ -2653,10 +2679,8 @@ static __inline__ int radeon_emit_scalars(drm_radeon_private_t *dev_priv,
2653 OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0)); 2679 OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
2654 OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); 2680 OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
2655 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1)); 2681 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
2656 OUT_RING_TABLE(cmdbuf->buf, sz); 2682 OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
2657 ADVANCE_RING(); 2683 ADVANCE_RING();
2658 cmdbuf->buf += sz * sizeof(int);
2659 cmdbuf->bufsz -= sz * sizeof(int);
2660 return 0; 2684 return 0;
2661} 2685}
2662 2686
@@ -2675,10 +2699,8 @@ static __inline__ int radeon_emit_scalars2(drm_radeon_private_t *dev_priv,
2675 OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0)); 2699 OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
2676 OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); 2700 OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
2677 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1)); 2701 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
2678 OUT_RING_TABLE(cmdbuf->buf, sz); 2702 OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
2679 ADVANCE_RING(); 2703 ADVANCE_RING();
2680 cmdbuf->buf += sz * sizeof(int);
2681 cmdbuf->bufsz -= sz * sizeof(int);
2682 return 0; 2704 return 0;
2683} 2705}
2684 2706
@@ -2696,11 +2718,9 @@ static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv,
2696 OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0)); 2718 OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
2697 OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); 2719 OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
2698 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1))); 2720 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
2699 OUT_RING_TABLE(cmdbuf->buf, sz); 2721 OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
2700 ADVANCE_RING(); 2722 ADVANCE_RING();
2701 2723
2702 cmdbuf->buf += sz * sizeof(int);
2703 cmdbuf->bufsz -= sz * sizeof(int);
2704 return 0; 2724 return 0;
2705} 2725}
2706 2726
@@ -2714,7 +2734,7 @@ static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
2714 2734
2715 if (!sz) 2735 if (!sz)
2716 return 0; 2736 return 0;
2717 if (sz * 4 > cmdbuf->bufsz) 2737 if (sz * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
2718 return -EINVAL; 2738 return -EINVAL;
2719 2739
2720 BEGIN_RING(5 + sz); 2740 BEGIN_RING(5 + sz);
@@ -2722,11 +2742,9 @@ static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
2722 OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0)); 2742 OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
2723 OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); 2743 OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
2724 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1))); 2744 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
2725 OUT_RING_TABLE(cmdbuf->buf, sz); 2745 OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
2726 ADVANCE_RING(); 2746 ADVANCE_RING();
2727 2747
2728 cmdbuf->buf += sz * sizeof(int);
2729 cmdbuf->bufsz -= sz * sizeof(int);
2730 return 0; 2748 return 0;
2731} 2749}
2732 2750
@@ -2748,11 +2766,9 @@ static int radeon_emit_packet3(struct drm_device * dev,
2748 } 2766 }
2749 2767
2750 BEGIN_RING(cmdsz); 2768 BEGIN_RING(cmdsz);
2751 OUT_RING_TABLE(cmdbuf->buf, cmdsz); 2769 OUT_RING_DRM_BUFFER(cmdbuf->buffer, cmdsz);
2752 ADVANCE_RING(); 2770 ADVANCE_RING();
2753 2771
2754 cmdbuf->buf += cmdsz * 4;
2755 cmdbuf->bufsz -= cmdsz * 4;
2756 return 0; 2772 return 0;
2757} 2773}
2758 2774
@@ -2805,16 +2821,16 @@ static int radeon_emit_packet3_cliprect(struct drm_device *dev,
2805 } 2821 }
2806 2822
2807 BEGIN_RING(cmdsz); 2823 BEGIN_RING(cmdsz);
2808 OUT_RING_TABLE(cmdbuf->buf, cmdsz); 2824 OUT_RING_DRM_BUFFER(cmdbuf->buffer, cmdsz);
2809 ADVANCE_RING(); 2825 ADVANCE_RING();
2810 2826
2811 } while (++i < cmdbuf->nbox); 2827 } while (++i < cmdbuf->nbox);
2812 if (cmdbuf->nbox == 1) 2828 if (cmdbuf->nbox == 1)
2813 cmdbuf->nbox = 0; 2829 cmdbuf->nbox = 0;
2814 2830
2831 return 0;
2815 out: 2832 out:
2816 cmdbuf->buf += cmdsz * 4; 2833 drm_buffer_advance(cmdbuf->buffer, cmdsz * 4);
2817 cmdbuf->bufsz -= cmdsz * 4;
2818 return 0; 2834 return 0;
2819} 2835}
2820 2836
@@ -2847,16 +2863,16 @@ static int radeon_emit_wait(struct drm_device * dev, int flags)
2847 return 0; 2863 return 0;
2848} 2864}
2849 2865
2850static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv) 2866static int radeon_cp_cmdbuf(struct drm_device *dev, void *data,
2867 struct drm_file *file_priv)
2851{ 2868{
2852 drm_radeon_private_t *dev_priv = dev->dev_private; 2869 drm_radeon_private_t *dev_priv = dev->dev_private;
2853 struct drm_device_dma *dma = dev->dma; 2870 struct drm_device_dma *dma = dev->dma;
2854 struct drm_buf *buf = NULL; 2871 struct drm_buf *buf = NULL;
2872 drm_radeon_cmd_header_t stack_header;
2855 int idx; 2873 int idx;
2856 drm_radeon_kcmd_buffer_t *cmdbuf = data; 2874 drm_radeon_kcmd_buffer_t *cmdbuf = data;
2857 drm_radeon_cmd_header_t header; 2875 int orig_nbox;
2858 int orig_nbox, orig_bufsz;
2859 char *kbuf = NULL;
2860 2876
2861 LOCK_TEST_WITH_RETURN(dev, file_priv); 2877 LOCK_TEST_WITH_RETURN(dev, file_priv);
2862 2878
@@ -2871,18 +2887,20 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
2871 * races between checking values and using those values in other code, 2887 * races between checking values and using those values in other code,
2872 * and simply to avoid a lot of function calls to copy in data. 2888 * and simply to avoid a lot of function calls to copy in data.
2873 */ 2889 */
2874 orig_bufsz = cmdbuf->bufsz; 2890 if (cmdbuf->bufsz != 0) {
2875 if (orig_bufsz != 0) { 2891 int rv;
2876 kbuf = kmalloc(cmdbuf->bufsz, GFP_KERNEL); 2892 void __user *buffer = cmdbuf->buffer;
2877 if (kbuf == NULL) 2893 rv = drm_buffer_alloc(&cmdbuf->buffer, cmdbuf->bufsz);
2878 return -ENOMEM; 2894 if (rv)
2879 if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf->buf, 2895 return rv;
2880 cmdbuf->bufsz)) { 2896 rv = drm_buffer_copy_from_user(cmdbuf->buffer, buffer,
2881 kfree(kbuf); 2897 cmdbuf->bufsz);
2882 return -EFAULT; 2898 if (rv) {
2899 drm_buffer_free(cmdbuf->buffer);
2900 return rv;
2883 } 2901 }
2884 cmdbuf->buf = kbuf; 2902 } else
2885 } 2903 goto done;
2886 2904
2887 orig_nbox = cmdbuf->nbox; 2905 orig_nbox = cmdbuf->nbox;
2888 2906
@@ -2890,24 +2908,23 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
2890 int temp; 2908 int temp;
2891 temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf); 2909 temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf);
2892 2910
2893 if (orig_bufsz != 0) 2911 drm_buffer_free(cmdbuf->buffer);
2894 kfree(kbuf);
2895 2912
2896 return temp; 2913 return temp;
2897 } 2914 }
2898 2915
2899 /* microcode_version != r300 */ 2916 /* microcode_version != r300 */
2900 while (cmdbuf->bufsz >= sizeof(header)) { 2917 while (drm_buffer_unprocessed(cmdbuf->buffer) >= sizeof(stack_header)) {
2901 2918
2902 header.i = *(int *)cmdbuf->buf; 2919 drm_radeon_cmd_header_t *header;
2903 cmdbuf->buf += sizeof(header); 2920 header = drm_buffer_read_object(cmdbuf->buffer,
2904 cmdbuf->bufsz -= sizeof(header); 2921 sizeof(stack_header), &stack_header);
2905 2922
2906 switch (header.header.cmd_type) { 2923 switch (header->header.cmd_type) {
2907 case RADEON_CMD_PACKET: 2924 case RADEON_CMD_PACKET:
2908 DRM_DEBUG("RADEON_CMD_PACKET\n"); 2925 DRM_DEBUG("RADEON_CMD_PACKET\n");
2909 if (radeon_emit_packets 2926 if (radeon_emit_packets
2910 (dev_priv, file_priv, header, cmdbuf)) { 2927 (dev_priv, file_priv, *header, cmdbuf)) {
2911 DRM_ERROR("radeon_emit_packets failed\n"); 2928 DRM_ERROR("radeon_emit_packets failed\n");
2912 goto err; 2929 goto err;
2913 } 2930 }
@@ -2915,7 +2932,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
2915 2932
2916 case RADEON_CMD_SCALARS: 2933 case RADEON_CMD_SCALARS:
2917 DRM_DEBUG("RADEON_CMD_SCALARS\n"); 2934 DRM_DEBUG("RADEON_CMD_SCALARS\n");
2918 if (radeon_emit_scalars(dev_priv, header, cmdbuf)) { 2935 if (radeon_emit_scalars(dev_priv, *header, cmdbuf)) {
2919 DRM_ERROR("radeon_emit_scalars failed\n"); 2936 DRM_ERROR("radeon_emit_scalars failed\n");
2920 goto err; 2937 goto err;
2921 } 2938 }
@@ -2923,7 +2940,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
2923 2940
2924 case RADEON_CMD_VECTORS: 2941 case RADEON_CMD_VECTORS:
2925 DRM_DEBUG("RADEON_CMD_VECTORS\n"); 2942 DRM_DEBUG("RADEON_CMD_VECTORS\n");
2926 if (radeon_emit_vectors(dev_priv, header, cmdbuf)) { 2943 if (radeon_emit_vectors(dev_priv, *header, cmdbuf)) {
2927 DRM_ERROR("radeon_emit_vectors failed\n"); 2944 DRM_ERROR("radeon_emit_vectors failed\n");
2928 goto err; 2945 goto err;
2929 } 2946 }
@@ -2931,7 +2948,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
2931 2948
2932 case RADEON_CMD_DMA_DISCARD: 2949 case RADEON_CMD_DMA_DISCARD:
2933 DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n"); 2950 DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
2934 idx = header.dma.buf_idx; 2951 idx = header->dma.buf_idx;
2935 if (idx < 0 || idx >= dma->buf_count) { 2952 if (idx < 0 || idx >= dma->buf_count) {
2936 DRM_ERROR("buffer index %d (of %d max)\n", 2953 DRM_ERROR("buffer index %d (of %d max)\n",
2937 idx, dma->buf_count - 1); 2954 idx, dma->buf_count - 1);
@@ -2968,7 +2985,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
2968 2985
2969 case RADEON_CMD_SCALARS2: 2986 case RADEON_CMD_SCALARS2:
2970 DRM_DEBUG("RADEON_CMD_SCALARS2\n"); 2987 DRM_DEBUG("RADEON_CMD_SCALARS2\n");
2971 if (radeon_emit_scalars2(dev_priv, header, cmdbuf)) { 2988 if (radeon_emit_scalars2(dev_priv, *header, cmdbuf)) {
2972 DRM_ERROR("radeon_emit_scalars2 failed\n"); 2989 DRM_ERROR("radeon_emit_scalars2 failed\n");
2973 goto err; 2990 goto err;
2974 } 2991 }
@@ -2976,37 +2993,36 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
2976 2993
2977 case RADEON_CMD_WAIT: 2994 case RADEON_CMD_WAIT:
2978 DRM_DEBUG("RADEON_CMD_WAIT\n"); 2995 DRM_DEBUG("RADEON_CMD_WAIT\n");
2979 if (radeon_emit_wait(dev, header.wait.flags)) { 2996 if (radeon_emit_wait(dev, header->wait.flags)) {
2980 DRM_ERROR("radeon_emit_wait failed\n"); 2997 DRM_ERROR("radeon_emit_wait failed\n");
2981 goto err; 2998 goto err;
2982 } 2999 }
2983 break; 3000 break;
2984 case RADEON_CMD_VECLINEAR: 3001 case RADEON_CMD_VECLINEAR:
2985 DRM_DEBUG("RADEON_CMD_VECLINEAR\n"); 3002 DRM_DEBUG("RADEON_CMD_VECLINEAR\n");
2986 if (radeon_emit_veclinear(dev_priv, header, cmdbuf)) { 3003 if (radeon_emit_veclinear(dev_priv, *header, cmdbuf)) {
2987 DRM_ERROR("radeon_emit_veclinear failed\n"); 3004 DRM_ERROR("radeon_emit_veclinear failed\n");
2988 goto err; 3005 goto err;
2989 } 3006 }
2990 break; 3007 break;
2991 3008
2992 default: 3009 default:
2993 DRM_ERROR("bad cmd_type %d at %p\n", 3010 DRM_ERROR("bad cmd_type %d at byte %d\n",
2994 header.header.cmd_type, 3011 header->header.cmd_type,
2995 cmdbuf->buf - sizeof(header)); 3012 cmdbuf->buffer->iterator);
2996 goto err; 3013 goto err;
2997 } 3014 }
2998 } 3015 }
2999 3016
3000 if (orig_bufsz != 0) 3017 drm_buffer_free(cmdbuf->buffer);
3001 kfree(kbuf);
3002 3018
3019 done:
3003 DRM_DEBUG("DONE\n"); 3020 DRM_DEBUG("DONE\n");
3004 COMMIT_RING(); 3021 COMMIT_RING();
3005 return 0; 3022 return 0;
3006 3023
3007 err: 3024 err:
3008 if (orig_bufsz != 0) 3025 drm_buffer_free(cmdbuf->buffer);
3009 kfree(kbuf);
3010 return -EINVAL; 3026 return -EINVAL;
3011} 3027}
3012 3028