From 48764bf43f746113fc77877d7e80f2df23ca4cbb Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 15 Sep 2009 22:57:32 +0200 Subject: drm/i915: add i915_lp_ring_sync helper This just waits until the hw passed the current ring position with cmd execution. This slightly changes the existing i915_wait_request function to make uninterruptible waiting possible - no point in returning to userspace while mucking around with the overlay, that piece of hw is just too fragile. Also replace a magic 0 with the symbolic constant (and kill the then superflous comment) while I was looking at the code. Signed-off-by: Daniel Vetter Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 49 ++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/i915/i915_gem.c') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index abfc27b0c2ea..7d1e9adf0f4c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1820,12 +1820,8 @@ i915_gem_retire_work_handler(struct work_struct *work) mutex_unlock(&dev->struct_mutex); } -/** - * Waits for a sequence number to be signaled, and cleans up the - * request and object lists appropriately for that event. - */ static int -i915_wait_request(struct drm_device *dev, uint32_t seqno) +i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible) { drm_i915_private_t *dev_priv = dev->dev_private; u32 ier; @@ -1852,10 +1848,15 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno) dev_priv->mm.waiting_gem_seqno = seqno; i915_user_irq_get(dev); - ret = wait_event_interruptible(dev_priv->irq_queue, - i915_seqno_passed(i915_get_gem_seqno(dev), - seqno) || - atomic_read(&dev_priv->mm.wedged)); + if (interruptible) + ret = wait_event_interruptible(dev_priv->irq_queue, + i915_seqno_passed(i915_get_gem_seqno(dev), seqno) || + atomic_read(&dev_priv->mm.wedged)); + else + wait_event(dev_priv->irq_queue, + i915_seqno_passed(i915_get_gem_seqno(dev), seqno) || + atomic_read(&dev_priv->mm.wedged)); + i915_user_irq_put(dev); dev_priv->mm.waiting_gem_seqno = 0; @@ -1879,6 +1880,34 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno) return ret; } +/** + * Waits for a sequence number to be signaled, and cleans up the + * request and object lists appropriately for that event. + */ +static int +i915_wait_request(struct drm_device *dev, uint32_t seqno) +{ + return i915_do_wait_request(dev, seqno, 1); +} + +/** + * Waits for the ring to finish up to the latest request. Usefull for waiting + * for flip events, e.g for the overlay support. */ +int i915_lp_ring_sync(struct drm_device *dev) +{ + uint32_t seqno; + int ret; + + seqno = i915_add_request(dev, NULL, 0); + + if (seqno == 0) + return -ENOMEM; + + ret = i915_do_wait_request(dev, seqno, 0); + BUG_ON(ret == -ERESTARTSYS); + return ret; +} + static void i915_gem_flush(struct drm_device *dev, uint32_t invalidate_domains, @@ -1947,7 +1976,7 @@ i915_gem_flush(struct drm_device *dev, #endif BEGIN_LP_RING(2); OUT_RING(cmd); - OUT_RING(0); /* noop */ + OUT_RING(MI_NOOP); ADVANCE_LP_RING(); } } -- cgit v1.2.3 From 5a5a0c64a99d7542c48c99d1a8bbb49e665842be Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 15 Sep 2009 22:57:36 +0200 Subject: drm/i915: implement fastpath for overlay flip waiting As long as the gpu can keep up, neither the cpu (waiting for gpu) nore the gpu (waiting for vblank to do an overlay flip) stalls. Signed-off-by: Daniel Vetter Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/i915_gem.c') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 7d1e9adf0f4c..5e579a41b6ad 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1583,7 +1583,7 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj) * * Returned sequence numbers are nonzero on success. */ -static uint32_t +uint32_t i915_add_request(struct drm_device *dev, struct drm_file *file_priv, uint32_t flush_domains) { @@ -1820,7 +1820,7 @@ i915_gem_retire_work_handler(struct work_struct *work) mutex_unlock(&dev->struct_mutex); } -static int +int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible) { drm_i915_private_t *dev_priv = dev->dev_private; -- cgit v1.2.3 From 1df4b35b61df27fc5b173fe2789d976e40e1dc22 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 15 Sep 2009 22:57:38 +0200 Subject: drm/i915: kill i915_lp_ring_sync It's not needed anymore. Signed-off-by: Daniel Vetter Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'drivers/gpu/drm/i915/i915_gem.c') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 5e579a41b6ad..19d25e5d8608 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1890,24 +1890,6 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno) return i915_do_wait_request(dev, seqno, 1); } -/** - * Waits for the ring to finish up to the latest request. Usefull for waiting - * for flip events, e.g for the overlay support. */ -int i915_lp_ring_sync(struct drm_device *dev) -{ - uint32_t seqno; - int ret; - - seqno = i915_add_request(dev, NULL, 0); - - if (seqno == 0) - return -ENOMEM; - - ret = i915_do_wait_request(dev, seqno, 0); - BUG_ON(ret == -ERESTARTSYS); - return ret; -} - static void i915_gem_flush(struct drm_device *dev, uint32_t invalidate_domains, -- cgit v1.2.3 From 44d98a614267c81a04ba9c7a0427c3a628985b7d Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 9 Oct 2009 11:39:40 +0800 Subject: drm/i915: Replace DRM_DEBUG with DRM_DEBUG_DRIVER Replace the DRM_DEBUG with DRM_DEBUG_DRIVER in generic i915 driver. Then the debug info can be obtained by adding the boot option of "drm.debug=0x02". At the same time the debug info in increase/decrease clock is also printed by using DRM_DEBUG_DRIVER instead of DRM_DEBUG_KMS. Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915/i915_gem.c') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 19d25e5d8608..2065b8f7e875 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1617,7 +1617,7 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv, OUT_RING(MI_USER_INTERRUPT); ADVANCE_LP_RING(); - DRM_DEBUG("%d\n", seqno); + DRM_DEBUG_DRIVER("%d\n", seqno); request->seqno = seqno; request->emitted_jiffies = jiffies; @@ -4367,7 +4367,7 @@ i915_gem_init_hws(struct drm_device *dev) memset(dev_priv->hw_status_page, 0, PAGE_SIZE); I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr); I915_READ(HWS_PGA); /* posting read */ - DRM_DEBUG("hws offset: 0x%08x\n", dev_priv->status_gfx_addr); + DRM_DEBUG_DRIVER("hws offset: 0x%08x\n", dev_priv->status_gfx_addr); return 0; } @@ -4801,7 +4801,7 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, user_data = (char __user *) (uintptr_t) args->data_ptr; obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; - DRM_DEBUG("obj_addr %p, %lld\n", obj_addr, args->size); + DRM_DEBUG_DRIVER("obj_addr %p, %lld\n", obj_addr, args->size); ret = copy_from_user(obj_addr, user_data, args->size); if (ret) return -EFAULT; -- cgit v1.2.3 From c8e0f93a381d1d76135e567f13a4418fce66fd95 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sun, 22 Nov 2009 03:49:37 +0100 Subject: drm/i915: Replace a calloc followed by copying data over it with malloc. Execbufs involve quite a bit of payload, to the extent that cache misses show up in the profiles here, and a suspicion that some of those cachelines may get evicted and then reloaded in the subsequent copy. This is still abstracted like drm_calloc_large since we want to check for size overflow, and because we want to choose between kmalloc and vmalloc on the fly. cairo's interface for malloc-with-calloc's-args was used as the model. Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/i915_gem.c') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2065b8f7e875..481c0ab888c8 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3563,8 +3563,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, return -EINVAL; } /* Copy in the exec list from userland */ - exec_list = drm_calloc_large(sizeof(*exec_list), args->buffer_count); - object_list = drm_calloc_large(sizeof(*object_list), args->buffer_count); + exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count); + object_list = drm_malloc_ab(sizeof(*object_list), args->buffer_count); if (exec_list == NULL || object_list == NULL) { DRM_ERROR("Failed to allocate exec or object list " "for %d buffers\n", -- cgit v1.2.3 From 6b95a207c1fd552e7d017837c5eaf1b0173a48c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 18 Nov 2009 11:25:18 -0500 Subject: drm/i915: Add intel implementation of the pageflip ioctl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Jakob Bornecrantz Acked-by: Thomas Hellström Review-by: Chris Wilson Signed-off-by: Jesse "Orange Smoothie" Barnes Signed-off-by: Kristian Høgsberg Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 64 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/i915_gem.c') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 481c0ab888c8..214fb1864710 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2771,6 +2771,22 @@ i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj) old_write_domain); } +void +i915_gem_object_flush_write_domain(struct drm_gem_object *obj) +{ + switch (obj->write_domain) { + case I915_GEM_DOMAIN_GTT: + i915_gem_object_flush_gtt_write_domain(obj); + break; + case I915_GEM_DOMAIN_CPU: + i915_gem_object_flush_cpu_write_domain(obj); + break; + default: + i915_gem_object_flush_gpu_write_domain(obj); + break; + } +} + /** * Moves a single object to the GTT read, and possibly write domain. * @@ -3536,6 +3552,41 @@ i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer *exec, return 0; } +static int +i915_gem_wait_for_pending_flip(struct drm_device *dev, + struct drm_gem_object **object_list, + int count) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj_priv; + DEFINE_WAIT(wait); + int i, ret = 0; + + for (;;) { + prepare_to_wait(&dev_priv->pending_flip_queue, + &wait, TASK_INTERRUPTIBLE); + for (i = 0; i < count; i++) { + obj_priv = object_list[i]->driver_private; + if (atomic_read(&obj_priv->pending_flip) > 0) + break; + } + if (i == count) + break; + + if (!signal_pending(current)) { + mutex_unlock(&dev->struct_mutex); + schedule(); + mutex_lock(&dev->struct_mutex); + continue; + } + ret = -ERESTARTSYS; + break; + } + finish_wait(&dev_priv->pending_flip_queue, &wait); + + return ret; +} + int i915_gem_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -3551,7 +3602,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, int ret, ret2, i, pinned = 0; uint64_t exec_offset; uint32_t seqno, flush_domains, reloc_index; - int pin_tries; + int pin_tries, flips; #if WATCH_EXEC DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", @@ -3623,6 +3674,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, } /* Look up object handles */ + flips = 0; for (i = 0; i < args->buffer_count; i++) { object_list[i] = drm_gem_object_lookup(dev, file_priv, exec_list[i].handle); @@ -3641,6 +3693,14 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, goto err; } obj_priv->in_execbuffer = true; + flips += atomic_read(&obj_priv->pending_flip); + } + + if (flips > 0) { + ret = i915_gem_wait_for_pending_flip(dev, object_list, + args->buffer_count); + if (ret) + goto err; } /* Pin and relocate */ @@ -4625,8 +4685,8 @@ i915_gem_load(struct drm_device *dev) for (i = 0; i < 8; i++) I915_WRITE(FENCE_REG_945_8 + (i * 4), 0); } - i915_gem_detect_bit_6_swizzle(dev); + init_waitqueue_head(&dev_priv->pending_flip_queue); } /* -- cgit v1.2.3 From ffb4728095b030f0885ea8e0907ee4ac57b130ee Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 7 Dec 2009 11:34:08 +0000 Subject: drm/i915: Drop a some common DRM_ERROR() These are handled by the error return being propagated to user-space and do not any add any information to the original error, so are useless. Signed-off-by: Chris Wilson Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu/drm/i915/i915_gem.c') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 214fb1864710..fd5363995044 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3660,14 +3660,12 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, i915_verify_inactive(dev, __FILE__, __LINE__); if (atomic_read(&dev_priv->mm.wedged)) { - DRM_ERROR("Execbuf while wedged\n"); mutex_unlock(&dev->struct_mutex); ret = -EIO; goto pre_mutex_err; } if (dev_priv->mm.suspended) { - DRM_ERROR("Execbuf while VT-switched.\n"); mutex_unlock(&dev->struct_mutex); ret = -EBUSY; goto pre_mutex_err; -- cgit v1.2.3 From f2b115e69d46344ae7afcaad5823496d2a0d8650 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Thu, 3 Dec 2009 17:14:42 -0500 Subject: drm/i915: Fix product names and #defines IGD* isn't a useful name. Replace with the codenames, as sourced from pci.ids. Signed-off-by: Adam Jackson [anholt: Fixed up for merge with pineview/ironlake changes] Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/i915_gem.c') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fd5363995044..5b46623d62d4 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1833,7 +1833,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible) return -EIO; if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) { - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) ier = I915_READ(DEIER) | I915_READ(GTIER); else ier = I915_READ(IER); -- cgit v1.2.3 From 5618ca6abc2d6f475b258badc017a5254cf43d1b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 2 Dec 2009 15:15:30 +0000 Subject: drm/i915: Set the error code after failing to insert new offset into mm ht. Signed-off-by: Chris Wilson Cc: stable@kernel.org Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/i915/i915_gem.c') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 5b46623d62d4..917b8377ae28 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1288,6 +1288,7 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj) list->hash.key = list->file_offset_node->start; if (drm_ht_insert_item(&mm->offset_hash, &list->hash)) { DRM_ERROR("failed to add to map hash\n"); + ret = -ENOMEM; goto out_free_mm; } -- cgit v1.2.3