aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c28
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h15
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c2
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c28
4 files changed, 63 insertions, 10 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index ea85d71cab0..d71c89f8802 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -588,9 +588,15 @@ static int i915_quiescent(struct drm_device * dev)
588static int i915_flush_ioctl(struct drm_device *dev, void *data, 588static int i915_flush_ioctl(struct drm_device *dev, void *data,
589 struct drm_file *file_priv) 589 struct drm_file *file_priv)
590{ 590{
591 LOCK_TEST_WITH_RETURN(dev, file_priv); 591 int ret;
592
593 RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
592 594
593 return i915_quiescent(dev); 595 mutex_lock(&dev->struct_mutex);
596 ret = i915_quiescent(dev);
597 mutex_unlock(&dev->struct_mutex);
598
599 return ret;
594} 600}
595 601
596static int i915_batchbuffer(struct drm_device *dev, void *data, 602static int i915_batchbuffer(struct drm_device *dev, void *data,
@@ -611,14 +617,16 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
611 DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n", 617 DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
612 batch->start, batch->used, batch->num_cliprects); 618 batch->start, batch->used, batch->num_cliprects);
613 619
614 LOCK_TEST_WITH_RETURN(dev, file_priv); 620 RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
615 621
616 if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects, 622 if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects,
617 batch->num_cliprects * 623 batch->num_cliprects *
618 sizeof(struct drm_clip_rect))) 624 sizeof(struct drm_clip_rect)))
619 return -EFAULT; 625 return -EFAULT;
620 626
627 mutex_lock(&dev->struct_mutex);
621 ret = i915_dispatch_batchbuffer(dev, batch); 628 ret = i915_dispatch_batchbuffer(dev, batch);
629 mutex_unlock(&dev->struct_mutex);
622 630
623 sarea_priv->last_dispatch = (int)hw_status[5]; 631 sarea_priv->last_dispatch = (int)hw_status[5];
624 return ret; 632 return ret;
@@ -637,7 +645,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
637 DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n", 645 DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
638 cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects); 646 cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
639 647
640 LOCK_TEST_WITH_RETURN(dev, file_priv); 648 RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
641 649
642 if (cmdbuf->num_cliprects && 650 if (cmdbuf->num_cliprects &&
643 DRM_VERIFYAREA_READ(cmdbuf->cliprects, 651 DRM_VERIFYAREA_READ(cmdbuf->cliprects,
@@ -647,7 +655,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
647 return -EFAULT; 655 return -EFAULT;
648 } 656 }
649 657
658 mutex_lock(&dev->struct_mutex);
650 ret = i915_dispatch_cmdbuffer(dev, cmdbuf); 659 ret = i915_dispatch_cmdbuffer(dev, cmdbuf);
660 mutex_unlock(&dev->struct_mutex);
651 if (ret) { 661 if (ret) {
652 DRM_ERROR("i915_dispatch_cmdbuffer failed\n"); 662 DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
653 return ret; 663 return ret;
@@ -660,11 +670,17 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
660static int i915_flip_bufs(struct drm_device *dev, void *data, 670static int i915_flip_bufs(struct drm_device *dev, void *data,
661 struct drm_file *file_priv) 671 struct drm_file *file_priv)
662{ 672{
673 int ret;
674
663 DRM_DEBUG("%s\n", __func__); 675 DRM_DEBUG("%s\n", __func__);
664 676
665 LOCK_TEST_WITH_RETURN(dev, file_priv); 677 RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
666 678
667 return i915_dispatch_flip(dev); 679 mutex_lock(&dev->struct_mutex);
680 ret = i915_dispatch_flip(dev);
681 mutex_unlock(&dev->struct_mutex);
682
683 return ret;
668} 684}
669 685
670static int i915_getparam(struct drm_device *dev, void *data, 686static int i915_getparam(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 87b071ab864..8547f0aeafc 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -285,6 +285,9 @@ typedef struct drm_i915_private {
285 */ 285 */
286 struct delayed_work retire_work; 286 struct delayed_work retire_work;
287 287
288 /** Work task for vblank-related ring access */
289 struct work_struct vblank_work;
290
288 uint32_t next_gem_seqno; 291 uint32_t next_gem_seqno;
289 292
290 /** 293 /**
@@ -435,6 +438,7 @@ extern int i915_irq_wait(struct drm_device *dev, void *data,
435void i915_user_irq_get(struct drm_device *dev); 438void i915_user_irq_get(struct drm_device *dev);
436void i915_user_irq_put(struct drm_device *dev); 439void i915_user_irq_put(struct drm_device *dev);
437 440
441extern void i915_gem_vblank_work_handler(struct work_struct *work);
438extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); 442extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
439extern void i915_driver_irq_preinstall(struct drm_device * dev); 443extern void i915_driver_irq_preinstall(struct drm_device * dev);
440extern int i915_driver_irq_postinstall(struct drm_device *dev); 444extern int i915_driver_irq_postinstall(struct drm_device *dev);
@@ -538,6 +542,17 @@ extern void intel_opregion_free(struct drm_device *dev);
538extern void opregion_asle_intr(struct drm_device *dev); 542extern void opregion_asle_intr(struct drm_device *dev);
539extern void opregion_enable_asle(struct drm_device *dev); 543extern void opregion_enable_asle(struct drm_device *dev);
540 544
545/**
546 * Lock test for when it's just for synchronization of ring access.
547 *
548 * In that case, we don't need to do it when GEM is initialized as nobody else
549 * has access to the ring.
550 */
551#define RING_LOCK_TEST_WITH_RETURN(dev, file_priv) do { \
552 if (((drm_i915_private_t *)dev->dev_private)->ring.ring_obj == NULL) \
553 LOCK_TEST_WITH_RETURN(dev, file_priv); \
554} while (0)
555
541#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg)) 556#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg))
542#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val)) 557#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
543#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg)) 558#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg))
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 90ae8a0369f..bb6e5a37efa 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2491,6 +2491,8 @@ i915_gem_load(struct drm_device *dev)
2491 INIT_LIST_HEAD(&dev_priv->mm.request_list); 2491 INIT_LIST_HEAD(&dev_priv->mm.request_list);
2492 INIT_DELAYED_WORK(&dev_priv->mm.retire_work, 2492 INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
2493 i915_gem_retire_work_handler); 2493 i915_gem_retire_work_handler);
2494 INIT_WORK(&dev_priv->mm.vblank_work,
2495 i915_gem_vblank_work_handler);
2494 dev_priv->mm.next_gem_seqno = 1; 2496 dev_priv->mm.next_gem_seqno = 1;
2495 2497
2496 i915_gem_detect_bit_6_swizzle(dev); 2498 i915_gem_detect_bit_6_swizzle(dev);
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index f295bdf16e2..d04c526410a 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -349,6 +349,21 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
349 return count; 349 return count;
350} 350}
351 351
352void
353i915_gem_vblank_work_handler(struct work_struct *work)
354{
355 drm_i915_private_t *dev_priv;
356 struct drm_device *dev;
357
358 dev_priv = container_of(work, drm_i915_private_t,
359 mm.vblank_work);
360 dev = dev_priv->dev;
361
362 mutex_lock(&dev->struct_mutex);
363 i915_vblank_tasklet(dev);
364 mutex_unlock(&dev->struct_mutex);
365}
366
352irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) 367irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
353{ 368{
354 struct drm_device *dev = (struct drm_device *) arg; 369 struct drm_device *dev = (struct drm_device *) arg;
@@ -422,8 +437,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
422 if (iir & I915_ASLE_INTERRUPT) 437 if (iir & I915_ASLE_INTERRUPT)
423 opregion_asle_intr(dev); 438 opregion_asle_intr(dev);
424 439
425 if (vblank && dev_priv->swaps_pending > 0) 440 if (vblank && dev_priv->swaps_pending > 0) {
426 drm_locked_tasklet(dev, i915_vblank_tasklet); 441 if (dev_priv->ring.ring_obj == NULL)
442 drm_locked_tasklet(dev, i915_vblank_tasklet);
443 else
444 schedule_work(&dev_priv->mm.vblank_work);
445 }
427 446
428 return IRQ_HANDLED; 447 return IRQ_HANDLED;
429} 448}
@@ -514,14 +533,15 @@ int i915_irq_emit(struct drm_device *dev, void *data,
514 drm_i915_irq_emit_t *emit = data; 533 drm_i915_irq_emit_t *emit = data;
515 int result; 534 int result;
516 535
517 LOCK_TEST_WITH_RETURN(dev, file_priv); 536 RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
518 537
519 if (!dev_priv) { 538 if (!dev_priv) {
520 DRM_ERROR("called with no initialization\n"); 539 DRM_ERROR("called with no initialization\n");
521 return -EINVAL; 540 return -EINVAL;
522 } 541 }
523 542 mutex_lock(&dev->struct_mutex);
524 result = i915_emit_irq(dev); 543 result = i915_emit_irq(dev);
544 mutex_unlock(&dev->struct_mutex);
525 545
526 if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) { 546 if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
527 DRM_ERROR("copy_to_user\n"); 547 DRM_ERROR("copy_to_user\n");