diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_state.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_state.c | 208 |
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 * | |||
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 | } |
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 | ||
2850 | static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv) | 2866 | static 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 | ||