diff options
Diffstat (limited to 'drivers/char/drm')
-rw-r--r-- | drivers/char/drm/drm_bufs.c | 4 | ||||
-rw-r--r-- | drivers/char/drm/drm_sysfs.c | 43 | ||||
-rw-r--r-- | drivers/char/drm/mga_drv.c | 1 | ||||
-rw-r--r-- | drivers/char/drm/r300_cmdbuf.c | 33 | ||||
-rw-r--r-- | drivers/char/drm/radeon_state.c | 109 | ||||
-rw-r--r-- | drivers/char/drm/savage_bci.c | 1 | ||||
-rw-r--r-- | drivers/char/drm/savage_state.c | 2 |
7 files changed, 180 insertions, 13 deletions
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 029baea33b62..6eafff13dab6 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c | |||
@@ -237,6 +237,8 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
237 | 237 | ||
238 | list = drm_alloc(sizeof(*list), DRM_MEM_MAPS); | 238 | list = drm_alloc(sizeof(*list), DRM_MEM_MAPS); |
239 | if (!list) { | 239 | if (!list) { |
240 | if (map->type == _DRM_REGISTERS) | ||
241 | drm_ioremapfree(map->handle, map->size, dev); | ||
240 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 242 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
241 | return -EINVAL; | 243 | return -EINVAL; |
242 | } | 244 | } |
@@ -252,6 +254,8 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
252 | map->offset; | 254 | map->offset; |
253 | ret = drm_map_handle(dev, &list->hash, user_token, 0); | 255 | ret = drm_map_handle(dev, &list->hash, user_token, 0); |
254 | if (ret) { | 256 | if (ret) { |
257 | if (map->type == _DRM_REGISTERS) | ||
258 | drm_ioremapfree(map->handle, map->size, dev); | ||
255 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 259 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
256 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); | 260 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); |
257 | mutex_unlock(&dev->struct_mutex); | 261 | mutex_unlock(&dev->struct_mutex); |
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c index 51ad98c685c3..ba4b8de83cf0 100644 --- a/drivers/char/drm/drm_sysfs.c +++ b/drivers/char/drm/drm_sysfs.c | |||
@@ -42,13 +42,24 @@ static CLASS_ATTR(version, S_IRUGO, version_show, NULL); | |||
42 | struct class *drm_sysfs_create(struct module *owner, char *name) | 42 | struct class *drm_sysfs_create(struct module *owner, char *name) |
43 | { | 43 | { |
44 | struct class *class; | 44 | struct class *class; |
45 | int err; | ||
45 | 46 | ||
46 | class = class_create(owner, name); | 47 | class = class_create(owner, name); |
47 | if (!class) | 48 | if (!class) { |
48 | return class; | 49 | err = -ENOMEM; |
50 | goto err_out; | ||
51 | } | ||
52 | |||
53 | err = class_create_file(class, &class_attr_version); | ||
54 | if (err) | ||
55 | goto err_out_class; | ||
49 | 56 | ||
50 | class_create_file(class, &class_attr_version); | ||
51 | return class; | 57 | return class; |
58 | |||
59 | err_out_class: | ||
60 | class_destroy(class); | ||
61 | err_out: | ||
62 | return ERR_PTR(err); | ||
52 | } | 63 | } |
53 | 64 | ||
54 | /** | 65 | /** |
@@ -96,20 +107,36 @@ static struct class_device_attribute class_device_attrs[] = { | |||
96 | struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head) | 107 | struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head) |
97 | { | 108 | { |
98 | struct class_device *class_dev; | 109 | struct class_device *class_dev; |
99 | int i; | 110 | int i, j, err; |
100 | 111 | ||
101 | class_dev = class_device_create(cs, NULL, | 112 | class_dev = class_device_create(cs, NULL, |
102 | MKDEV(DRM_MAJOR, head->minor), | 113 | MKDEV(DRM_MAJOR, head->minor), |
103 | &(head->dev->pdev)->dev, | 114 | &(head->dev->pdev)->dev, |
104 | "card%d", head->minor); | 115 | "card%d", head->minor); |
105 | if (!class_dev) | 116 | if (!class_dev) { |
106 | return NULL; | 117 | err = -ENOMEM; |
118 | goto err_out; | ||
119 | } | ||
107 | 120 | ||
108 | class_set_devdata(class_dev, head); | 121 | class_set_devdata(class_dev, head); |
109 | 122 | ||
110 | for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) | 123 | for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) { |
111 | class_device_create_file(class_dev, &class_device_attrs[i]); | 124 | err = class_device_create_file(class_dev, |
125 | &class_device_attrs[i]); | ||
126 | if (err) | ||
127 | goto err_out_files; | ||
128 | } | ||
129 | |||
112 | return class_dev; | 130 | return class_dev; |
131 | |||
132 | err_out_files: | ||
133 | if (i > 0) | ||
134 | for (j = 0; j < i; j++) | ||
135 | class_device_remove_file(class_dev, | ||
136 | &class_device_attrs[i]); | ||
137 | class_device_unregister(class_dev); | ||
138 | err_out: | ||
139 | return ERR_PTR(err); | ||
113 | } | 140 | } |
114 | 141 | ||
115 | /** | 142 | /** |
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c index e30f556b79f1..be49dbb9ec3f 100644 --- a/drivers/char/drm/mga_drv.c +++ b/drivers/char/drm/mga_drv.c | |||
@@ -47,6 +47,7 @@ static struct drm_driver driver = { | |||
47 | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | | 47 | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | |
48 | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | | 48 | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | |
49 | DRIVER_IRQ_VBL, | 49 | DRIVER_IRQ_VBL, |
50 | .dev_priv_size = sizeof(drm_mga_buf_priv_t), | ||
50 | .load = mga_driver_load, | 51 | .load = mga_driver_load, |
51 | .unload = mga_driver_unload, | 52 | .unload = mga_driver_unload, |
52 | .lastclose = mga_driver_lastclose, | 53 | .lastclose = mga_driver_lastclose, |
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index 26bdf2ca59d7..d14477ba3679 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c | |||
@@ -538,6 +538,36 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, | |||
538 | return 0; | 538 | return 0; |
539 | } | 539 | } |
540 | 540 | ||
541 | static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv, | ||
542 | drm_radeon_kcmd_buffer_t *cmdbuf) | ||
543 | { | ||
544 | u32 *cmd = (u32 *) cmdbuf->buf; | ||
545 | int count, ret; | ||
546 | RING_LOCALS; | ||
547 | |||
548 | count=(cmd[0]>>16) & 0x3fff; | ||
549 | |||
550 | if ((cmd[1] & 0x8000ffff) != 0x80000810) { | ||
551 | DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); | ||
552 | return DRM_ERR(EINVAL); | ||
553 | } | ||
554 | ret = r300_check_offset(dev_priv, cmd[2]); | ||
555 | if (ret) { | ||
556 | DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); | ||
557 | return DRM_ERR(EINVAL); | ||
558 | } | ||
559 | |||
560 | BEGIN_RING(count+2); | ||
561 | OUT_RING(cmd[0]); | ||
562 | OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1); | ||
563 | ADVANCE_RING(); | ||
564 | |||
565 | cmdbuf->buf += (count+2)*4; | ||
566 | cmdbuf->bufsz -= (count+2)*4; | ||
567 | |||
568 | return 0; | ||
569 | } | ||
570 | |||
541 | static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, | 571 | static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, |
542 | drm_radeon_kcmd_buffer_t *cmdbuf) | 572 | drm_radeon_kcmd_buffer_t *cmdbuf) |
543 | { | 573 | { |
@@ -578,10 +608,11 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, | |||
578 | case RADEON_CNTL_BITBLT_MULTI: | 608 | case RADEON_CNTL_BITBLT_MULTI: |
579 | return r300_emit_bitblt_multi(dev_priv, cmdbuf); | 609 | return r300_emit_bitblt_multi(dev_priv, cmdbuf); |
580 | 610 | ||
611 | case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ | ||
612 | return r300_emit_indx_buffer(dev_priv, cmdbuf); | ||
581 | case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ | 613 | case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ |
582 | case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ | 614 | case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ |
583 | case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ | 615 | case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ |
584 | case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ | ||
585 | case RADEON_WAIT_FOR_IDLE: | 616 | case RADEON_WAIT_FOR_IDLE: |
586 | case RADEON_CP_NOP: | 617 | case RADEON_CP_NOP: |
587 | /* these packets are safe */ | 618 | /* these packets are safe */ |
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index feac5f005d47..6e04fdd732ac 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c | |||
@@ -275,6 +275,8 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * | |||
275 | unsigned int *cmdsz) | 275 | unsigned int *cmdsz) |
276 | { | 276 | { |
277 | u32 *cmd = (u32 *) cmdbuf->buf; | 277 | u32 *cmd = (u32 *) cmdbuf->buf; |
278 | u32 offset, narrays; | ||
279 | int count, i, k; | ||
278 | 280 | ||
279 | *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16); | 281 | *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16); |
280 | 282 | ||
@@ -288,10 +290,106 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * | |||
288 | return DRM_ERR(EINVAL); | 290 | return DRM_ERR(EINVAL); |
289 | } | 291 | } |
290 | 292 | ||
291 | /* Check client state and fix it up if necessary */ | 293 | switch(cmd[0] & 0xff00) { |
292 | if (cmd[0] & 0x8000) { /* MSB of opcode: next DWORD GUI_CNTL */ | 294 | /* XXX Are there old drivers needing other packets? */ |
293 | u32 offset; | ||
294 | 295 | ||
296 | case RADEON_3D_DRAW_IMMD: | ||
297 | case RADEON_3D_DRAW_VBUF: | ||
298 | case RADEON_3D_DRAW_INDX: | ||
299 | case RADEON_WAIT_FOR_IDLE: | ||
300 | case RADEON_CP_NOP: | ||
301 | case RADEON_3D_CLEAR_ZMASK: | ||
302 | /* case RADEON_CP_NEXT_CHAR: | ||
303 | case RADEON_CP_PLY_NEXTSCAN: | ||
304 | case RADEON_CP_SET_SCISSORS: */ /* probably safe but will never need them? */ | ||
305 | /* these packets are safe */ | ||
306 | break; | ||
307 | |||
308 | case RADEON_CP_3D_DRAW_IMMD_2: | ||
309 | case RADEON_CP_3D_DRAW_VBUF_2: | ||
310 | case RADEON_CP_3D_DRAW_INDX_2: | ||
311 | case RADEON_3D_CLEAR_HIZ: | ||
312 | /* safe but r200 only */ | ||
313 | if (dev_priv->microcode_version != UCODE_R200) { | ||
314 | DRM_ERROR("Invalid 3d packet for r100-class chip\n"); | ||
315 | return DRM_ERR(EINVAL); | ||
316 | } | ||
317 | break; | ||
318 | |||
319 | case RADEON_3D_LOAD_VBPNTR: | ||
320 | count = (cmd[0] >> 16) & 0x3fff; | ||
321 | |||
322 | if (count > 18) { /* 12 arrays max */ | ||
323 | DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", | ||
324 | count); | ||
325 | return DRM_ERR(EINVAL); | ||
326 | } | ||
327 | |||
328 | /* carefully check packet contents */ | ||
329 | narrays = cmd[1] & ~0xc000; | ||
330 | k = 0; | ||
331 | i = 2; | ||
332 | while ((k < narrays) && (i < (count + 2))) { | ||
333 | i++; /* skip attribute field */ | ||
334 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) { | ||
335 | DRM_ERROR | ||
336 | ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", | ||
337 | k, i); | ||
338 | return DRM_ERR(EINVAL); | ||
339 | } | ||
340 | k++; | ||
341 | i++; | ||
342 | if (k == narrays) | ||
343 | break; | ||
344 | /* have one more to process, they come in pairs */ | ||
345 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) { | ||
346 | DRM_ERROR | ||
347 | ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", | ||
348 | k, i); | ||
349 | return DRM_ERR(EINVAL); | ||
350 | } | ||
351 | k++; | ||
352 | i++; | ||
353 | } | ||
354 | /* do the counts match what we expect ? */ | ||
355 | if ((k != narrays) || (i != (count + 2))) { | ||
356 | DRM_ERROR | ||
357 | ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n", | ||
358 | k, i, narrays, count + 1); | ||
359 | return DRM_ERR(EINVAL); | ||
360 | } | ||
361 | break; | ||
362 | |||
363 | case RADEON_3D_RNDR_GEN_INDX_PRIM: | ||
364 | if (dev_priv->microcode_version != UCODE_R100) { | ||
365 | DRM_ERROR("Invalid 3d packet for r200-class chip\n"); | ||
366 | return DRM_ERR(EINVAL); | ||
367 | } | ||
368 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[1])) { | ||
369 | DRM_ERROR("Invalid rndr_gen_indx offset\n"); | ||
370 | return DRM_ERR(EINVAL); | ||
371 | } | ||
372 | break; | ||
373 | |||
374 | case RADEON_CP_INDX_BUFFER: | ||
375 | if (dev_priv->microcode_version != UCODE_R200) { | ||
376 | DRM_ERROR("Invalid 3d packet for r100-class chip\n"); | ||
377 | return DRM_ERR(EINVAL); | ||
378 | } | ||
379 | if ((cmd[1] & 0x8000ffff) != 0x80000810) { | ||
380 | DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); | ||
381 | return DRM_ERR(EINVAL); | ||
382 | } | ||
383 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[2])) { | ||
384 | DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); | ||
385 | return DRM_ERR(EINVAL); | ||
386 | } | ||
387 | break; | ||
388 | |||
389 | case RADEON_CNTL_HOSTDATA_BLT: | ||
390 | case RADEON_CNTL_PAINT_MULTI: | ||
391 | case RADEON_CNTL_BITBLT_MULTI: | ||
392 | /* MSB of opcode: next DWORD GUI_CNTL */ | ||
295 | if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 393 | if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
296 | | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { | 394 | | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { |
297 | offset = cmd[2] << 10; | 395 | offset = cmd[2] << 10; |
@@ -313,6 +411,11 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * | |||
313 | } | 411 | } |
314 | cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10; | 412 | cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10; |
315 | } | 413 | } |
414 | break; | ||
415 | |||
416 | default: | ||
417 | DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00); | ||
418 | return DRM_ERR(EINVAL); | ||
316 | } | 419 | } |
317 | 420 | ||
318 | return 0; | 421 | return 0; |
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c index 59c7520bf9a2..a9a84f88df5e 100644 --- a/drivers/char/drm/savage_bci.c +++ b/drivers/char/drm/savage_bci.c | |||
@@ -728,6 +728,7 @@ static int savage_do_init_bci(drm_device_t * dev, drm_savage_init_t * init) | |||
728 | dev_priv->status = NULL; | 728 | dev_priv->status = NULL; |
729 | } | 729 | } |
730 | if (dev_priv->dma_type == SAVAGE_DMA_AGP && init->buffers_offset) { | 730 | if (dev_priv->dma_type == SAVAGE_DMA_AGP && init->buffers_offset) { |
731 | dev->agp_buffer_token = init->buffers_offset; | ||
731 | dev->agp_buffer_map = drm_core_findmap(dev, | 732 | dev->agp_buffer_map = drm_core_findmap(dev, |
732 | init->buffers_offset); | 733 | init->buffers_offset); |
733 | if (!dev->agp_buffer_map) { | 734 | if (!dev->agp_buffer_map) { |
diff --git a/drivers/char/drm/savage_state.c b/drivers/char/drm/savage_state.c index ef2581d16146..1ca1e9cb5a33 100644 --- a/drivers/char/drm/savage_state.c +++ b/drivers/char/drm/savage_state.c | |||
@@ -994,7 +994,7 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) | |||
994 | if (cmdbuf.size) { | 994 | if (cmdbuf.size) { |
995 | kcmd_addr = drm_alloc(cmdbuf.size * 8, DRM_MEM_DRIVER); | 995 | kcmd_addr = drm_alloc(cmdbuf.size * 8, DRM_MEM_DRIVER); |
996 | if (kcmd_addr == NULL) | 996 | if (kcmd_addr == NULL) |
997 | return ENOMEM; | 997 | return DRM_ERR(ENOMEM); |
998 | 998 | ||
999 | if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf.cmd_addr, | 999 | if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf.cmd_addr, |
1000 | cmdbuf.size * 8)) | 1000 | cmdbuf.size * 8)) |