diff options
author | Len Brown <len.brown@intel.com> | 2009-04-05 02:14:15 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-04-05 02:14:15 -0400 |
commit | 478c6a43fcbc6c11609f8cee7c7b57223907754f (patch) | |
tree | a7f7952099da60d33032aed6de9c0c56c9f8779e /drivers/gpu/drm/i915/i915_dma.c | |
parent | 8a3f257c704e02aee9869decd069a806b45be3f1 (diff) | |
parent | 6bb597507f9839b13498781e481f5458aea33620 (diff) |
Merge branch 'linus' into release
Conflicts:
arch/x86/kernel/cpu/cpufreq/longhaul.c
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_dma.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 129 |
1 files changed, 82 insertions, 47 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 638686904e0..a000cf02882 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -41,7 +41,6 @@ | |||
41 | int i915_wait_ring(struct drm_device * dev, int n, const char *caller) | 41 | int i915_wait_ring(struct drm_device * dev, int n, const char *caller) |
42 | { | 42 | { |
43 | drm_i915_private_t *dev_priv = dev->dev_private; | 43 | drm_i915_private_t *dev_priv = dev->dev_private; |
44 | struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; | ||
45 | drm_i915_ring_buffer_t *ring = &(dev_priv->ring); | 44 | drm_i915_ring_buffer_t *ring = &(dev_priv->ring); |
46 | u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD; | 45 | u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD; |
47 | u32 last_acthd = I915_READ(acthd_reg); | 46 | u32 last_acthd = I915_READ(acthd_reg); |
@@ -58,8 +57,12 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) | |||
58 | if (ring->space >= n) | 57 | if (ring->space >= n) |
59 | return 0; | 58 | return 0; |
60 | 59 | ||
61 | if (master_priv->sarea_priv) | 60 | if (dev->primary->master) { |
62 | master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; | 61 | struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; |
62 | if (master_priv->sarea_priv) | ||
63 | master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; | ||
64 | } | ||
65 | |||
63 | 66 | ||
64 | if (ring->head != last_head) | 67 | if (ring->head != last_head) |
65 | i = 0; | 68 | i = 0; |
@@ -356,7 +359,7 @@ static int validate_cmd(int cmd) | |||
356 | return ret; | 359 | return ret; |
357 | } | 360 | } |
358 | 361 | ||
359 | static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwords) | 362 | static int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords) |
360 | { | 363 | { |
361 | drm_i915_private_t *dev_priv = dev->dev_private; | 364 | drm_i915_private_t *dev_priv = dev->dev_private; |
362 | int i; | 365 | int i; |
@@ -370,8 +373,7 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwor | |||
370 | for (i = 0; i < dwords;) { | 373 | for (i = 0; i < dwords;) { |
371 | int cmd, sz; | 374 | int cmd, sz; |
372 | 375 | ||
373 | if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) | 376 | cmd = buffer[i]; |
374 | return -EINVAL; | ||
375 | 377 | ||
376 | if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords) | 378 | if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords) |
377 | return -EINVAL; | 379 | return -EINVAL; |
@@ -379,11 +381,7 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwor | |||
379 | OUT_RING(cmd); | 381 | OUT_RING(cmd); |
380 | 382 | ||
381 | while (++i, --sz) { | 383 | while (++i, --sz) { |
382 | if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], | 384 | OUT_RING(buffer[i]); |
383 | sizeof(cmd))) { | ||
384 | return -EINVAL; | ||
385 | } | ||
386 | OUT_RING(cmd); | ||
387 | } | 385 | } |
388 | } | 386 | } |
389 | 387 | ||
@@ -397,17 +395,13 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwor | |||
397 | 395 | ||
398 | int | 396 | int |
399 | i915_emit_box(struct drm_device *dev, | 397 | i915_emit_box(struct drm_device *dev, |
400 | struct drm_clip_rect __user *boxes, | 398 | struct drm_clip_rect *boxes, |
401 | int i, int DR1, int DR4) | 399 | int i, int DR1, int DR4) |
402 | { | 400 | { |
403 | drm_i915_private_t *dev_priv = dev->dev_private; | 401 | drm_i915_private_t *dev_priv = dev->dev_private; |
404 | struct drm_clip_rect box; | 402 | struct drm_clip_rect box = boxes[i]; |
405 | RING_LOCALS; | 403 | RING_LOCALS; |
406 | 404 | ||
407 | if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) { | ||
408 | return -EFAULT; | ||
409 | } | ||
410 | |||
411 | if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { | 405 | if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { |
412 | DRM_ERROR("Bad box %d,%d..%d,%d\n", | 406 | DRM_ERROR("Bad box %d,%d..%d,%d\n", |
413 | box.x1, box.y1, box.x2, box.y2); | 407 | box.x1, box.y1, box.x2, box.y2); |
@@ -460,7 +454,9 @@ static void i915_emit_breadcrumb(struct drm_device *dev) | |||
460 | } | 454 | } |
461 | 455 | ||
462 | static int i915_dispatch_cmdbuffer(struct drm_device * dev, | 456 | static int i915_dispatch_cmdbuffer(struct drm_device * dev, |
463 | drm_i915_cmdbuffer_t * cmd) | 457 | drm_i915_cmdbuffer_t *cmd, |
458 | struct drm_clip_rect *cliprects, | ||
459 | void *cmdbuf) | ||
464 | { | 460 | { |
465 | int nbox = cmd->num_cliprects; | 461 | int nbox = cmd->num_cliprects; |
466 | int i = 0, count, ret; | 462 | int i = 0, count, ret; |
@@ -476,13 +472,13 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev, | |||
476 | 472 | ||
477 | for (i = 0; i < count; i++) { | 473 | for (i = 0; i < count; i++) { |
478 | if (i < nbox) { | 474 | if (i < nbox) { |
479 | ret = i915_emit_box(dev, cmd->cliprects, i, | 475 | ret = i915_emit_box(dev, cliprects, i, |
480 | cmd->DR1, cmd->DR4); | 476 | cmd->DR1, cmd->DR4); |
481 | if (ret) | 477 | if (ret) |
482 | return ret; | 478 | return ret; |
483 | } | 479 | } |
484 | 480 | ||
485 | ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4); | 481 | ret = i915_emit_cmds(dev, cmdbuf, cmd->sz / 4); |
486 | if (ret) | 482 | if (ret) |
487 | return ret; | 483 | return ret; |
488 | } | 484 | } |
@@ -492,10 +488,10 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev, | |||
492 | } | 488 | } |
493 | 489 | ||
494 | static int i915_dispatch_batchbuffer(struct drm_device * dev, | 490 | static int i915_dispatch_batchbuffer(struct drm_device * dev, |
495 | drm_i915_batchbuffer_t * batch) | 491 | drm_i915_batchbuffer_t * batch, |
492 | struct drm_clip_rect *cliprects) | ||
496 | { | 493 | { |
497 | drm_i915_private_t *dev_priv = dev->dev_private; | 494 | drm_i915_private_t *dev_priv = dev->dev_private; |
498 | struct drm_clip_rect __user *boxes = batch->cliprects; | ||
499 | int nbox = batch->num_cliprects; | 495 | int nbox = batch->num_cliprects; |
500 | int i = 0, count; | 496 | int i = 0, count; |
501 | RING_LOCALS; | 497 | RING_LOCALS; |
@@ -511,7 +507,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, | |||
511 | 507 | ||
512 | for (i = 0; i < count; i++) { | 508 | for (i = 0; i < count; i++) { |
513 | if (i < nbox) { | 509 | if (i < nbox) { |
514 | int ret = i915_emit_box(dev, boxes, i, | 510 | int ret = i915_emit_box(dev, cliprects, i, |
515 | batch->DR1, batch->DR4); | 511 | batch->DR1, batch->DR4); |
516 | if (ret) | 512 | if (ret) |
517 | return ret; | 513 | return ret; |
@@ -626,6 +622,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, | |||
626 | master_priv->sarea_priv; | 622 | master_priv->sarea_priv; |
627 | drm_i915_batchbuffer_t *batch = data; | 623 | drm_i915_batchbuffer_t *batch = data; |
628 | int ret; | 624 | int ret; |
625 | struct drm_clip_rect *cliprects = NULL; | ||
629 | 626 | ||
630 | if (!dev_priv->allow_batchbuffer) { | 627 | if (!dev_priv->allow_batchbuffer) { |
631 | DRM_ERROR("Batchbuffer ioctl disabled\n"); | 628 | DRM_ERROR("Batchbuffer ioctl disabled\n"); |
@@ -637,17 +634,35 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, | |||
637 | 634 | ||
638 | RING_LOCK_TEST_WITH_RETURN(dev, file_priv); | 635 | RING_LOCK_TEST_WITH_RETURN(dev, file_priv); |
639 | 636 | ||
640 | if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects, | 637 | if (batch->num_cliprects < 0) |
641 | batch->num_cliprects * | 638 | return -EINVAL; |
642 | sizeof(struct drm_clip_rect))) | 639 | |
643 | return -EFAULT; | 640 | if (batch->num_cliprects) { |
641 | cliprects = drm_calloc(batch->num_cliprects, | ||
642 | sizeof(struct drm_clip_rect), | ||
643 | DRM_MEM_DRIVER); | ||
644 | if (cliprects == NULL) | ||
645 | return -ENOMEM; | ||
646 | |||
647 | ret = copy_from_user(cliprects, batch->cliprects, | ||
648 | batch->num_cliprects * | ||
649 | sizeof(struct drm_clip_rect)); | ||
650 | if (ret != 0) | ||
651 | goto fail_free; | ||
652 | } | ||
644 | 653 | ||
645 | mutex_lock(&dev->struct_mutex); | 654 | mutex_lock(&dev->struct_mutex); |
646 | ret = i915_dispatch_batchbuffer(dev, batch); | 655 | ret = i915_dispatch_batchbuffer(dev, batch, cliprects); |
647 | mutex_unlock(&dev->struct_mutex); | 656 | mutex_unlock(&dev->struct_mutex); |
648 | 657 | ||
649 | if (sarea_priv) | 658 | if (sarea_priv) |
650 | sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); | 659 | sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); |
660 | |||
661 | fail_free: | ||
662 | drm_free(cliprects, | ||
663 | batch->num_cliprects * sizeof(struct drm_clip_rect), | ||
664 | DRM_MEM_DRIVER); | ||
665 | |||
651 | return ret; | 666 | return ret; |
652 | } | 667 | } |
653 | 668 | ||
@@ -659,6 +674,8 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, | |||
659 | drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) | 674 | drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) |
660 | master_priv->sarea_priv; | 675 | master_priv->sarea_priv; |
661 | drm_i915_cmdbuffer_t *cmdbuf = data; | 676 | drm_i915_cmdbuffer_t *cmdbuf = data; |
677 | struct drm_clip_rect *cliprects = NULL; | ||
678 | void *batch_data; | ||
662 | int ret; | 679 | int ret; |
663 | 680 | ||
664 | DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n", | 681 | DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n", |
@@ -666,25 +683,50 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, | |||
666 | 683 | ||
667 | RING_LOCK_TEST_WITH_RETURN(dev, file_priv); | 684 | RING_LOCK_TEST_WITH_RETURN(dev, file_priv); |
668 | 685 | ||
669 | if (cmdbuf->num_cliprects && | 686 | if (cmdbuf->num_cliprects < 0) |
670 | DRM_VERIFYAREA_READ(cmdbuf->cliprects, | 687 | return -EINVAL; |
671 | cmdbuf->num_cliprects * | 688 | |
672 | sizeof(struct drm_clip_rect))) { | 689 | batch_data = drm_alloc(cmdbuf->sz, DRM_MEM_DRIVER); |
673 | DRM_ERROR("Fault accessing cliprects\n"); | 690 | if (batch_data == NULL) |
674 | return -EFAULT; | 691 | return -ENOMEM; |
692 | |||
693 | ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz); | ||
694 | if (ret != 0) | ||
695 | goto fail_batch_free; | ||
696 | |||
697 | if (cmdbuf->num_cliprects) { | ||
698 | cliprects = drm_calloc(cmdbuf->num_cliprects, | ||
699 | sizeof(struct drm_clip_rect), | ||
700 | DRM_MEM_DRIVER); | ||
701 | if (cliprects == NULL) | ||
702 | goto fail_batch_free; | ||
703 | |||
704 | ret = copy_from_user(cliprects, cmdbuf->cliprects, | ||
705 | cmdbuf->num_cliprects * | ||
706 | sizeof(struct drm_clip_rect)); | ||
707 | if (ret != 0) | ||
708 | goto fail_clip_free; | ||
675 | } | 709 | } |
676 | 710 | ||
677 | mutex_lock(&dev->struct_mutex); | 711 | mutex_lock(&dev->struct_mutex); |
678 | ret = i915_dispatch_cmdbuffer(dev, cmdbuf); | 712 | ret = i915_dispatch_cmdbuffer(dev, cmdbuf, cliprects, batch_data); |
679 | mutex_unlock(&dev->struct_mutex); | 713 | mutex_unlock(&dev->struct_mutex); |
680 | if (ret) { | 714 | if (ret) { |
681 | DRM_ERROR("i915_dispatch_cmdbuffer failed\n"); | 715 | DRM_ERROR("i915_dispatch_cmdbuffer failed\n"); |
682 | return ret; | 716 | goto fail_batch_free; |
683 | } | 717 | } |
684 | 718 | ||
685 | if (sarea_priv) | 719 | if (sarea_priv) |
686 | sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); | 720 | sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); |
687 | return 0; | 721 | |
722 | fail_batch_free: | ||
723 | drm_free(batch_data, cmdbuf->sz, DRM_MEM_DRIVER); | ||
724 | fail_clip_free: | ||
725 | drm_free(cliprects, | ||
726 | cmdbuf->num_cliprects * sizeof(struct drm_clip_rect), | ||
727 | DRM_MEM_DRIVER); | ||
728 | |||
729 | return ret; | ||
688 | } | 730 | } |
689 | 731 | ||
690 | static int i915_flip_bufs(struct drm_device *dev, void *data, | 732 | static int i915_flip_bufs(struct drm_device *dev, void *data, |
@@ -880,7 +922,7 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size, | |||
880 | * Some of the preallocated space is taken by the GTT | 922 | * Some of the preallocated space is taken by the GTT |
881 | * and popup. GTT is 1K per MB of aperture size, and popup is 4K. | 923 | * and popup. GTT is 1K per MB of aperture size, and popup is 4K. |
882 | */ | 924 | */ |
883 | if (IS_G4X(dev)) | 925 | if (IS_G4X(dev) || IS_IGD(dev)) |
884 | overhead = 4096; | 926 | overhead = 4096; |
885 | else | 927 | else |
886 | overhead = (*aperture_size / 1024) + 4096; | 928 | overhead = (*aperture_size / 1024) + 4096; |
@@ -988,13 +1030,6 @@ static int i915_load_modeset_init(struct drm_device *dev) | |||
988 | if (ret) | 1030 | if (ret) |
989 | goto destroy_ringbuffer; | 1031 | goto destroy_ringbuffer; |
990 | 1032 | ||
991 | /* FIXME: re-add hotplug support */ | ||
992 | #if 0 | ||
993 | ret = drm_hotplug_init(dev); | ||
994 | if (ret) | ||
995 | goto destroy_ringbuffer; | ||
996 | #endif | ||
997 | |||
998 | /* Always safe in the mode setting case. */ | 1033 | /* Always safe in the mode setting case. */ |
999 | /* FIXME: do pre/post-mode set stuff in core KMS code */ | 1034 | /* FIXME: do pre/post-mode set stuff in core KMS code */ |
1000 | dev->vblank_disable_allowed = 1; | 1035 | dev->vblank_disable_allowed = 1; |
@@ -1007,7 +1042,7 @@ static int i915_load_modeset_init(struct drm_device *dev) | |||
1007 | 1042 | ||
1008 | intel_modeset_init(dev); | 1043 | intel_modeset_init(dev); |
1009 | 1044 | ||
1010 | drm_helper_initial_config(dev, false); | 1045 | drm_helper_initial_config(dev); |
1011 | 1046 | ||
1012 | return 0; | 1047 | return 0; |
1013 | 1048 | ||
@@ -1057,7 +1092,7 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master) | |||
1057 | int i915_driver_load(struct drm_device *dev, unsigned long flags) | 1092 | int i915_driver_load(struct drm_device *dev, unsigned long flags) |
1058 | { | 1093 | { |
1059 | struct drm_i915_private *dev_priv = dev->dev_private; | 1094 | struct drm_i915_private *dev_priv = dev->dev_private; |
1060 | unsigned long base, size; | 1095 | resource_size_t base, size; |
1061 | int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1; | 1096 | int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1; |
1062 | 1097 | ||
1063 | /* i915 has 4 more counters */ | 1098 | /* i915 has 4 more counters */ |