aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_state.c
diff options
context:
space:
mode:
authorPauli Nieminen <suokkos@gmail.com>2010-02-01 12:11:16 -0500
committerDave Airlie <airlied@redhat.com>2010-02-22 18:46:20 -0500
commitb4fe945405e477cded91772b4fec854705443dd5 (patch)
tree4fb175511947cfd9980ca74413692f96561d1512 /drivers/gpu/drm/radeon/radeon_state.c
parent7a9f0dd9c49425e2b0e39ada4757bc7a38c84873 (diff)
drm/radeon: Fix memory allocation failures in the preKMS command stream checking.
Allocation of single large block of memory may fail under memory presure. drm_buffer object can hold one large block of data in multiple independ pages which preents alloation failures. This patch converts all access to command stream to use drm_buffer interface. All direct access to array has to go tough drm_buffer functions to get correct pointer. Outputting the command stream to ring buffer needs to be awear of the split nature of drm_buffer. The output operation requires the new OUT_RING_DRM_BUFFER. Signed-off-by: Pauli Nieminen <suokkos@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_state.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_state.c197
1 files changed, 103 insertions, 94 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c
index 38537d971a3e..44b6d66b0ab3 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,26 @@ 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 }
104 break; 108 break;
105 109
106 case RADEON_EMIT_PP_CNTL: 110 case RADEON_EMIT_PP_CNTL:
107 if (radeon_check_and_fixup_offset(dev_priv, file_priv, 111 data = drm_buffer_pointer_to_dword(buf,
108 &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) { 112 (RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4);
113
114 if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
109 DRM_ERROR("Invalid colour buffer offset\n"); 115 DRM_ERROR("Invalid colour buffer offset\n");
110 return -EINVAL; 116 return -EINVAL;
111 } 117 }
@@ -117,8 +123,8 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
117 case R200_EMIT_PP_TXOFFSET_3: 123 case R200_EMIT_PP_TXOFFSET_3:
118 case R200_EMIT_PP_TXOFFSET_4: 124 case R200_EMIT_PP_TXOFFSET_4:
119 case R200_EMIT_PP_TXOFFSET_5: 125 case R200_EMIT_PP_TXOFFSET_5:
120 if (radeon_check_and_fixup_offset(dev_priv, file_priv, 126 data = drm_buffer_pointer_to_dword(buf, 0);
121 &data[0])) { 127 if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
122 DRM_ERROR("Invalid R200 texture offset\n"); 128 DRM_ERROR("Invalid R200 texture offset\n");
123 return -EINVAL; 129 return -EINVAL;
124 } 130 }
@@ -127,8 +133,9 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
127 case RADEON_EMIT_PP_TXFILTER_0: 133 case RADEON_EMIT_PP_TXFILTER_0:
128 case RADEON_EMIT_PP_TXFILTER_1: 134 case RADEON_EMIT_PP_TXFILTER_1:
129 case RADEON_EMIT_PP_TXFILTER_2: 135 case RADEON_EMIT_PP_TXFILTER_2:
130 if (radeon_check_and_fixup_offset(dev_priv, file_priv, 136 data = drm_buffer_pointer_to_dword(buf,
131 &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) { 137 (RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4);
138 if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
132 DRM_ERROR("Invalid R100 texture offset\n"); 139 DRM_ERROR("Invalid R100 texture offset\n");
133 return -EINVAL; 140 return -EINVAL;
134 } 141 }
@@ -142,9 +149,10 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
142 case R200_EMIT_PP_CUBIC_OFFSETS_5:{ 149 case R200_EMIT_PP_CUBIC_OFFSETS_5:{
143 int i; 150 int i;
144 for (i = 0; i < 5; i++) { 151 for (i = 0; i < 5; i++) {
152 data = drm_buffer_pointer_to_dword(buf, i);
145 if (radeon_check_and_fixup_offset(dev_priv, 153 if (radeon_check_and_fixup_offset(dev_priv,
146 file_priv, 154 file_priv,
147 &data[i])) { 155 data)) {
148 DRM_ERROR 156 DRM_ERROR
149 ("Invalid R200 cubic texture offset\n"); 157 ("Invalid R200 cubic texture offset\n");
150 return -EINVAL; 158 return -EINVAL;
@@ -158,9 +166,10 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
158 case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{ 166 case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{
159 int i; 167 int i;
160 for (i = 0; i < 5; i++) { 168 for (i = 0; i < 5; i++) {
169 data = drm_buffer_pointer_to_dword(buf, i);
161 if (radeon_check_and_fixup_offset(dev_priv, 170 if (radeon_check_and_fixup_offset(dev_priv,
162 file_priv, 171 file_priv,
163 &data[i])) { 172 data)) {
164 DRM_ERROR 173 DRM_ERROR
165 ("Invalid R100 cubic texture offset\n"); 174 ("Invalid R100 cubic texture offset\n");
166 return -EINVAL; 175 return -EINVAL;
@@ -269,23 +278,24 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
269 cmdbuf, 278 cmdbuf,
270 unsigned int *cmdsz) 279 unsigned int *cmdsz)
271{ 280{
272 u32 *cmd = (u32 *) cmdbuf->buf; 281 u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
273 u32 offset, narrays; 282 u32 offset, narrays;
274 int count, i, k; 283 int count, i, k;
275 284
276 *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16); 285 count = ((*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16);
286 *cmdsz = 2 + count;
277 287
278 if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) { 288 if ((*cmd & 0xc0000000) != RADEON_CP_PACKET3) {
279 DRM_ERROR("Not a type 3 packet\n"); 289 DRM_ERROR("Not a type 3 packet\n");
280 return -EINVAL; 290 return -EINVAL;
281 } 291 }
282 292
283 if (4 * *cmdsz > cmdbuf->bufsz) { 293 if (4 * *cmdsz > drm_buffer_unprocessed(cmdbuf->buffer)) {
284 DRM_ERROR("Packet size larger than size of data provided\n"); 294 DRM_ERROR("Packet size larger than size of data provided\n");
285 return -EINVAL; 295 return -EINVAL;
286 } 296 }
287 297
288 switch(cmd[0] & 0xff00) { 298 switch (*cmd & 0xff00) {
289 /* XXX Are there old drivers needing other packets? */ 299 /* XXX Are there old drivers needing other packets? */
290 300
291 case RADEON_3D_DRAW_IMMD: 301 case RADEON_3D_DRAW_IMMD:
@@ -312,7 +322,6 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
312 break; 322 break;
313 323
314 case RADEON_3D_LOAD_VBPNTR: 324 case RADEON_3D_LOAD_VBPNTR:
315 count = (cmd[0] >> 16) & 0x3fff;
316 325
317 if (count > 18) { /* 12 arrays max */ 326 if (count > 18) { /* 12 arrays max */
318 DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", 327 DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
@@ -321,13 +330,16 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
321 } 330 }
322 331
323 /* carefully check packet contents */ 332 /* carefully check packet contents */
324 narrays = cmd[1] & ~0xc000; 333 cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
334
335 narrays = *cmd & ~0xc000;
325 k = 0; 336 k = 0;
326 i = 2; 337 i = 2;
327 while ((k < narrays) && (i < (count + 2))) { 338 while ((k < narrays) && (i < (count + 2))) {
328 i++; /* skip attribute field */ 339 i++; /* skip attribute field */
340 cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
329 if (radeon_check_and_fixup_offset(dev_priv, file_priv, 341 if (radeon_check_and_fixup_offset(dev_priv, file_priv,
330 &cmd[i])) { 342 cmd)) {
331 DRM_ERROR 343 DRM_ERROR
332 ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", 344 ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
333 k, i); 345 k, i);
@@ -338,8 +350,10 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
338 if (k == narrays) 350 if (k == narrays)
339 break; 351 break;
340 /* have one more to process, they come in pairs */ 352 /* have one more to process, they come in pairs */
353 cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
354
341 if (radeon_check_and_fixup_offset(dev_priv, 355 if (radeon_check_and_fixup_offset(dev_priv,
342 file_priv, &cmd[i])) 356 file_priv, cmd))
343 { 357 {
344 DRM_ERROR 358 DRM_ERROR
345 ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", 359 ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
@@ -363,7 +377,9 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
363 DRM_ERROR("Invalid 3d packet for r200-class chip\n"); 377 DRM_ERROR("Invalid 3d packet for r200-class chip\n");
364 return -EINVAL; 378 return -EINVAL;
365 } 379 }
366 if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[1])) { 380
381 cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
382 if (radeon_check_and_fixup_offset(dev_priv, file_priv, cmd)) {
367 DRM_ERROR("Invalid rndr_gen_indx offset\n"); 383 DRM_ERROR("Invalid rndr_gen_indx offset\n");
368 return -EINVAL; 384 return -EINVAL;
369 } 385 }
@@ -374,12 +390,15 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
374 DRM_ERROR("Invalid 3d packet for r100-class chip\n"); 390 DRM_ERROR("Invalid 3d packet for r100-class chip\n");
375 return -EINVAL; 391 return -EINVAL;
376 } 392 }
377 if ((cmd[1] & 0x8000ffff) != 0x80000810) { 393
378 DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); 394 cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
395 if ((*cmd & 0x8000ffff) != 0x80000810) {
396 DRM_ERROR("Invalid indx_buffer reg address %08X\n", *cmd);
379 return -EINVAL; 397 return -EINVAL;
380 } 398 }
381 if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[2])) { 399 cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
382 DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); 400 if (radeon_check_and_fixup_offset(dev_priv, file_priv, cmd)) {
401 DRM_ERROR("Invalid indx_buffer offset is %08X\n", *cmd);
383 return -EINVAL; 402 return -EINVAL;
384 } 403 }
385 break; 404 break;
@@ -388,31 +407,34 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
388 case RADEON_CNTL_PAINT_MULTI: 407 case RADEON_CNTL_PAINT_MULTI:
389 case RADEON_CNTL_BITBLT_MULTI: 408 case RADEON_CNTL_BITBLT_MULTI:
390 /* MSB of opcode: next DWORD GUI_CNTL */ 409 /* MSB of opcode: next DWORD GUI_CNTL */
391 if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL 410 cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
411 if (*cmd & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
392 | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { 412 | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
393 offset = cmd[2] << 10; 413 u32 *cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
414 offset = *cmd2 << 10;
394 if (radeon_check_and_fixup_offset 415 if (radeon_check_and_fixup_offset
395 (dev_priv, file_priv, &offset)) { 416 (dev_priv, file_priv, &offset)) {
396 DRM_ERROR("Invalid first packet offset\n"); 417 DRM_ERROR("Invalid first packet offset\n");
397 return -EINVAL; 418 return -EINVAL;
398 } 419 }
399 cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10; 420 *cmd2 = (*cmd2 & 0xffc00000) | offset >> 10;
400 } 421 }
401 422
402 if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) && 423 if ((*cmd & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
403 (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { 424 (*cmd & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
404 offset = cmd[3] << 10; 425 u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3);
426 offset = *cmd << 10;
405 if (radeon_check_and_fixup_offset 427 if (radeon_check_and_fixup_offset
406 (dev_priv, file_priv, &offset)) { 428 (dev_priv, file_priv, &offset)) {
407 DRM_ERROR("Invalid second packet offset\n"); 429 DRM_ERROR("Invalid second packet offset\n");
408 return -EINVAL; 430 return -EINVAL;
409 } 431 }
410 cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10; 432 *cmd3 = (*cmd3 & 0xffc00000) | offset >> 10;
411 } 433 }
412 break; 434 break;
413 435
414 default: 436 default:
415 DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00); 437 DRM_ERROR("Invalid packet type %x\n", *cmd & 0xff00);
416 return -EINVAL; 438 return -EINVAL;
417 } 439 }
418 440
@@ -2611,7 +2633,6 @@ static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
2611{ 2633{
2612 int id = (int)header.packet.packet_id; 2634 int id = (int)header.packet.packet_id;
2613 int sz, reg; 2635 int sz, reg;
2614 int *data = (int *)cmdbuf->buf;
2615 RING_LOCALS; 2636 RING_LOCALS;
2616 2637
2617 if (id >= RADEON_MAX_STATE_PACKETS) 2638 if (id >= RADEON_MAX_STATE_PACKETS)
@@ -2620,23 +2641,22 @@ static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
2620 sz = packet[id].len; 2641 sz = packet[id].len;
2621 reg = packet[id].start; 2642 reg = packet[id].start;
2622 2643
2623 if (sz * sizeof(int) > cmdbuf->bufsz) { 2644 if (sz * sizeof(u32) > drm_buffer_unprocessed(cmdbuf->buffer)) {
2624 DRM_ERROR("Packet size provided larger than data provided\n"); 2645 DRM_ERROR("Packet size provided larger than data provided\n");
2625 return -EINVAL; 2646 return -EINVAL;
2626 } 2647 }
2627 2648
2628 if (radeon_check_and_fixup_packets(dev_priv, file_priv, id, data)) { 2649 if (radeon_check_and_fixup_packets(dev_priv, file_priv, id,
2650 cmdbuf->buffer)) {
2629 DRM_ERROR("Packet verification failed\n"); 2651 DRM_ERROR("Packet verification failed\n");
2630 return -EINVAL; 2652 return -EINVAL;
2631 } 2653 }
2632 2654
2633 BEGIN_RING(sz + 1); 2655 BEGIN_RING(sz + 1);
2634 OUT_RING(CP_PACKET0(reg, (sz - 1))); 2656 OUT_RING(CP_PACKET0(reg, (sz - 1)));
2635 OUT_RING_TABLE(data, sz); 2657 OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
2636 ADVANCE_RING(); 2658 ADVANCE_RING();
2637 2659
2638 cmdbuf->buf += sz * sizeof(int);
2639 cmdbuf->bufsz -= sz * sizeof(int);
2640 return 0; 2660 return 0;
2641} 2661}
2642 2662
@@ -2653,10 +2673,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)); 2673 OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
2654 OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); 2674 OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
2655 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1)); 2675 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
2656 OUT_RING_TABLE(cmdbuf->buf, sz); 2676 OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
2657 ADVANCE_RING(); 2677 ADVANCE_RING();
2658 cmdbuf->buf += sz * sizeof(int);
2659 cmdbuf->bufsz -= sz * sizeof(int);
2660 return 0; 2678 return 0;
2661} 2679}
2662 2680
@@ -2675,10 +2693,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)); 2693 OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
2676 OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); 2694 OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
2677 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1)); 2695 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
2678 OUT_RING_TABLE(cmdbuf->buf, sz); 2696 OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
2679 ADVANCE_RING(); 2697 ADVANCE_RING();
2680 cmdbuf->buf += sz * sizeof(int);
2681 cmdbuf->bufsz -= sz * sizeof(int);
2682 return 0; 2698 return 0;
2683} 2699}
2684 2700
@@ -2696,11 +2712,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)); 2712 OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
2697 OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); 2713 OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
2698 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1))); 2714 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
2699 OUT_RING_TABLE(cmdbuf->buf, sz); 2715 OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
2700 ADVANCE_RING(); 2716 ADVANCE_RING();
2701 2717
2702 cmdbuf->buf += sz * sizeof(int);
2703 cmdbuf->bufsz -= sz * sizeof(int);
2704 return 0; 2718 return 0;
2705} 2719}
2706 2720
@@ -2714,7 +2728,7 @@ static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
2714 2728
2715 if (!sz) 2729 if (!sz)
2716 return 0; 2730 return 0;
2717 if (sz * 4 > cmdbuf->bufsz) 2731 if (sz * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
2718 return -EINVAL; 2732 return -EINVAL;
2719 2733
2720 BEGIN_RING(5 + sz); 2734 BEGIN_RING(5 + sz);
@@ -2722,11 +2736,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)); 2736 OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
2723 OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); 2737 OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
2724 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1))); 2738 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
2725 OUT_RING_TABLE(cmdbuf->buf, sz); 2739 OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
2726 ADVANCE_RING(); 2740 ADVANCE_RING();
2727 2741
2728 cmdbuf->buf += sz * sizeof(int);
2729 cmdbuf->bufsz -= sz * sizeof(int);
2730 return 0; 2742 return 0;
2731} 2743}
2732 2744
@@ -2748,11 +2760,9 @@ static int radeon_emit_packet3(struct drm_device * dev,
2748 } 2760 }
2749 2761
2750 BEGIN_RING(cmdsz); 2762 BEGIN_RING(cmdsz);
2751 OUT_RING_TABLE(cmdbuf->buf, cmdsz); 2763 OUT_RING_DRM_BUFFER(cmdbuf->buffer, cmdsz);
2752 ADVANCE_RING(); 2764 ADVANCE_RING();
2753 2765
2754 cmdbuf->buf += cmdsz * 4;
2755 cmdbuf->bufsz -= cmdsz * 4;
2756 return 0; 2766 return 0;
2757} 2767}
2758 2768
@@ -2805,16 +2815,16 @@ static int radeon_emit_packet3_cliprect(struct drm_device *dev,
2805 } 2815 }
2806 2816
2807 BEGIN_RING(cmdsz); 2817 BEGIN_RING(cmdsz);
2808 OUT_RING_TABLE(cmdbuf->buf, cmdsz); 2818 OUT_RING_DRM_BUFFER(cmdbuf->buffer, cmdsz);
2809 ADVANCE_RING(); 2819 ADVANCE_RING();
2810 2820
2811 } while (++i < cmdbuf->nbox); 2821 } while (++i < cmdbuf->nbox);
2812 if (cmdbuf->nbox == 1) 2822 if (cmdbuf->nbox == 1)
2813 cmdbuf->nbox = 0; 2823 cmdbuf->nbox = 0;
2814 2824
2825 return 0;
2815 out: 2826 out:
2816 cmdbuf->buf += cmdsz * 4; 2827 drm_buffer_advance(cmdbuf->buffer, cmdsz * 4);
2817 cmdbuf->bufsz -= cmdsz * 4;
2818 return 0; 2828 return 0;
2819} 2829}
2820 2830
@@ -2847,16 +2857,16 @@ static int radeon_emit_wait(struct drm_device * dev, int flags)
2847 return 0; 2857 return 0;
2848} 2858}
2849 2859
2850static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv) 2860static int radeon_cp_cmdbuf(struct drm_device *dev, void *data,
2861 struct drm_file *file_priv)
2851{ 2862{
2852 drm_radeon_private_t *dev_priv = dev->dev_private; 2863 drm_radeon_private_t *dev_priv = dev->dev_private;
2853 struct drm_device_dma *dma = dev->dma; 2864 struct drm_device_dma *dma = dev->dma;
2854 struct drm_buf *buf = NULL; 2865 struct drm_buf *buf = NULL;
2866 drm_radeon_cmd_header_t stack_header;
2855 int idx; 2867 int idx;
2856 drm_radeon_kcmd_buffer_t *cmdbuf = data; 2868 drm_radeon_kcmd_buffer_t *cmdbuf = data;
2857 drm_radeon_cmd_header_t header; 2869 int orig_nbox;
2858 int orig_nbox, orig_bufsz;
2859 char *kbuf = NULL;
2860 2870
2861 LOCK_TEST_WITH_RETURN(dev, file_priv); 2871 LOCK_TEST_WITH_RETURN(dev, file_priv);
2862 2872
@@ -2871,17 +2881,16 @@ 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, 2881 * 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. 2882 * and simply to avoid a lot of function calls to copy in data.
2873 */ 2883 */
2874 orig_bufsz = cmdbuf->bufsz; 2884 if (cmdbuf->bufsz != 0) {
2875 if (orig_bufsz != 0) { 2885 int rv;
2876 kbuf = kmalloc(cmdbuf->bufsz, GFP_KERNEL); 2886 void __user *buffer = cmdbuf->buffer;
2877 if (kbuf == NULL) 2887 rv = drm_buffer_alloc(&cmdbuf->buffer, cmdbuf->bufsz);
2878 return -ENOMEM; 2888 if (rv)
2879 if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf->buf, 2889 return rv;
2880 cmdbuf->bufsz)) { 2890 rv = drm_buffer_copy_from_user(cmdbuf->buffer, buffer,
2881 kfree(kbuf); 2891 cmdbuf->bufsz);
2882 return -EFAULT; 2892 if (rv)
2883 } 2893 return rv;
2884 cmdbuf->buf = kbuf;
2885 } 2894 }
2886 2895
2887 orig_nbox = cmdbuf->nbox; 2896 orig_nbox = cmdbuf->nbox;
@@ -2890,24 +2899,24 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
2890 int temp; 2899 int temp;
2891 temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf); 2900 temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf);
2892 2901
2893 if (orig_bufsz != 0) 2902 if (cmdbuf->bufsz != 0)
2894 kfree(kbuf); 2903 drm_buffer_free(cmdbuf->buffer);
2895 2904
2896 return temp; 2905 return temp;
2897 } 2906 }
2898 2907
2899 /* microcode_version != r300 */ 2908 /* microcode_version != r300 */
2900 while (cmdbuf->bufsz >= sizeof(header)) { 2909 while (drm_buffer_unprocessed(cmdbuf->buffer) >= sizeof(stack_header)) {
2901 2910
2902 header.i = *(int *)cmdbuf->buf; 2911 drm_radeon_cmd_header_t *header;
2903 cmdbuf->buf += sizeof(header); 2912 header = drm_buffer_read_object(cmdbuf->buffer,
2904 cmdbuf->bufsz -= sizeof(header); 2913 sizeof(stack_header), &stack_header);
2905 2914
2906 switch (header.header.cmd_type) { 2915 switch (header->header.cmd_type) {
2907 case RADEON_CMD_PACKET: 2916 case RADEON_CMD_PACKET:
2908 DRM_DEBUG("RADEON_CMD_PACKET\n"); 2917 DRM_DEBUG("RADEON_CMD_PACKET\n");
2909 if (radeon_emit_packets 2918 if (radeon_emit_packets
2910 (dev_priv, file_priv, header, cmdbuf)) { 2919 (dev_priv, file_priv, *header, cmdbuf)) {
2911 DRM_ERROR("radeon_emit_packets failed\n"); 2920 DRM_ERROR("radeon_emit_packets failed\n");
2912 goto err; 2921 goto err;
2913 } 2922 }
@@ -2915,7 +2924,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
2915 2924
2916 case RADEON_CMD_SCALARS: 2925 case RADEON_CMD_SCALARS:
2917 DRM_DEBUG("RADEON_CMD_SCALARS\n"); 2926 DRM_DEBUG("RADEON_CMD_SCALARS\n");
2918 if (radeon_emit_scalars(dev_priv, header, cmdbuf)) { 2927 if (radeon_emit_scalars(dev_priv, *header, cmdbuf)) {
2919 DRM_ERROR("radeon_emit_scalars failed\n"); 2928 DRM_ERROR("radeon_emit_scalars failed\n");
2920 goto err; 2929 goto err;
2921 } 2930 }
@@ -2923,7 +2932,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
2923 2932
2924 case RADEON_CMD_VECTORS: 2933 case RADEON_CMD_VECTORS:
2925 DRM_DEBUG("RADEON_CMD_VECTORS\n"); 2934 DRM_DEBUG("RADEON_CMD_VECTORS\n");
2926 if (radeon_emit_vectors(dev_priv, header, cmdbuf)) { 2935 if (radeon_emit_vectors(dev_priv, *header, cmdbuf)) {
2927 DRM_ERROR("radeon_emit_vectors failed\n"); 2936 DRM_ERROR("radeon_emit_vectors failed\n");
2928 goto err; 2937 goto err;
2929 } 2938 }
@@ -2931,7 +2940,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
2931 2940
2932 case RADEON_CMD_DMA_DISCARD: 2941 case RADEON_CMD_DMA_DISCARD:
2933 DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n"); 2942 DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
2934 idx = header.dma.buf_idx; 2943 idx = header->dma.buf_idx;
2935 if (idx < 0 || idx >= dma->buf_count) { 2944 if (idx < 0 || idx >= dma->buf_count) {
2936 DRM_ERROR("buffer index %d (of %d max)\n", 2945 DRM_ERROR("buffer index %d (of %d max)\n",
2937 idx, dma->buf_count - 1); 2946 idx, dma->buf_count - 1);
@@ -2968,7 +2977,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
2968 2977
2969 case RADEON_CMD_SCALARS2: 2978 case RADEON_CMD_SCALARS2:
2970 DRM_DEBUG("RADEON_CMD_SCALARS2\n"); 2979 DRM_DEBUG("RADEON_CMD_SCALARS2\n");
2971 if (radeon_emit_scalars2(dev_priv, header, cmdbuf)) { 2980 if (radeon_emit_scalars2(dev_priv, *header, cmdbuf)) {
2972 DRM_ERROR("radeon_emit_scalars2 failed\n"); 2981 DRM_ERROR("radeon_emit_scalars2 failed\n");
2973 goto err; 2982 goto err;
2974 } 2983 }
@@ -2976,37 +2985,37 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
2976 2985
2977 case RADEON_CMD_WAIT: 2986 case RADEON_CMD_WAIT:
2978 DRM_DEBUG("RADEON_CMD_WAIT\n"); 2987 DRM_DEBUG("RADEON_CMD_WAIT\n");
2979 if (radeon_emit_wait(dev, header.wait.flags)) { 2988 if (radeon_emit_wait(dev, header->wait.flags)) {
2980 DRM_ERROR("radeon_emit_wait failed\n"); 2989 DRM_ERROR("radeon_emit_wait failed\n");
2981 goto err; 2990 goto err;
2982 } 2991 }
2983 break; 2992 break;
2984 case RADEON_CMD_VECLINEAR: 2993 case RADEON_CMD_VECLINEAR:
2985 DRM_DEBUG("RADEON_CMD_VECLINEAR\n"); 2994 DRM_DEBUG("RADEON_CMD_VECLINEAR\n");
2986 if (radeon_emit_veclinear(dev_priv, header, cmdbuf)) { 2995 if (radeon_emit_veclinear(dev_priv, *header, cmdbuf)) {
2987 DRM_ERROR("radeon_emit_veclinear failed\n"); 2996 DRM_ERROR("radeon_emit_veclinear failed\n");
2988 goto err; 2997 goto err;
2989 } 2998 }
2990 break; 2999 break;
2991 3000
2992 default: 3001 default:
2993 DRM_ERROR("bad cmd_type %d at %p\n", 3002 DRM_ERROR("bad cmd_type %d at byte %d\n",
2994 header.header.cmd_type, 3003 header->header.cmd_type,
2995 cmdbuf->buf - sizeof(header)); 3004 cmdbuf->buffer->iterator);
2996 goto err; 3005 goto err;
2997 } 3006 }
2998 } 3007 }
2999 3008
3000 if (orig_bufsz != 0) 3009 if (cmdbuf->bufsz != 0)
3001 kfree(kbuf); 3010 drm_buffer_free(cmdbuf->buffer);
3002 3011
3003 DRM_DEBUG("DONE\n"); 3012 DRM_DEBUG("DONE\n");
3004 COMMIT_RING(); 3013 COMMIT_RING();
3005 return 0; 3014 return 0;
3006 3015
3007 err: 3016 err:
3008 if (orig_bufsz != 0) 3017 if (cmdbuf->bufsz != 0)
3009 kfree(kbuf); 3018 drm_buffer_free(cmdbuf->buffer);
3010 return -EINVAL; 3019 return -EINVAL;
3011} 3020}
3012 3021