diff options
author | Pauli Nieminen <suokkos@gmail.com> | 2010-02-01 12:11:16 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-02-22 18:46:20 -0500 |
commit | b4fe945405e477cded91772b4fec854705443dd5 (patch) | |
tree | 4fb175511947cfd9980ca74413692f96561d1512 /drivers/gpu/drm/radeon/radeon_state.c | |
parent | 7a9f0dd9c49425e2b0e39ada4757bc7a38c84873 (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.c | 197 |
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 * | |||
91 | static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * | 92 | static __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 | ||
2850 | static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv) | 2860 | static 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 | ||