diff options
| author | Thomas Hellstrom <thellstrom@vmware.com> | 2010-02-08 04:57:25 -0500 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2010-02-10 21:06:05 -0500 |
| commit | 85b9e4878f3b16993fba871c0c68d0948ec9c7c6 (patch) | |
| tree | 44e6ad34d467341be0cfea6605ed50c2e92b77a6 | |
| parent | a87897edbae2d60db7bcb6bb0a75e82013d68305 (diff) | |
drm/vmwgfx: Fix a circular locking dependency bug.
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 17 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_irq.c | 13 |
3 files changed, 14 insertions, 19 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 3e4e670d3216..356dc935ec13 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | |||
| @@ -113,6 +113,7 @@ struct vmw_fifo_state { | |||
| 113 | unsigned long static_buffer_size; | 113 | unsigned long static_buffer_size; |
| 114 | bool using_bounce_buffer; | 114 | bool using_bounce_buffer; |
| 115 | uint32_t capabilities; | 115 | uint32_t capabilities; |
| 116 | struct mutex fifo_mutex; | ||
| 116 | struct rw_semaphore rwsem; | 117 | struct rw_semaphore rwsem; |
| 117 | }; | 118 | }; |
| 118 | 119 | ||
| @@ -213,7 +214,7 @@ struct vmw_private { | |||
| 213 | * Fencing and IRQs. | 214 | * Fencing and IRQs. |
| 214 | */ | 215 | */ |
| 215 | 216 | ||
| 216 | uint32_t fence_seq; | 217 | atomic_t fence_seq; |
| 217 | wait_queue_head_t fence_queue; | 218 | wait_queue_head_t fence_queue; |
| 218 | wait_queue_head_t fifo_queue; | 219 | wait_queue_head_t fifo_queue; |
| 219 | atomic_t fence_queue_waiters; | 220 | atomic_t fence_queue_waiters; |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index 4157547cc6e4..39d43a01d846 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | |||
| @@ -74,6 +74,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | |||
| 74 | fifo->reserved_size = 0; | 74 | fifo->reserved_size = 0; |
| 75 | fifo->using_bounce_buffer = false; | 75 | fifo->using_bounce_buffer = false; |
| 76 | 76 | ||
| 77 | mutex_init(&fifo->fifo_mutex); | ||
| 77 | init_rwsem(&fifo->rwsem); | 78 | init_rwsem(&fifo->rwsem); |
| 78 | 79 | ||
| 79 | /* | 80 | /* |
| @@ -117,7 +118,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | |||
| 117 | (unsigned int) min, | 118 | (unsigned int) min, |
| 118 | (unsigned int) fifo->capabilities); | 119 | (unsigned int) fifo->capabilities); |
| 119 | 120 | ||
| 120 | dev_priv->fence_seq = dev_priv->last_read_sequence; | 121 | atomic_set(&dev_priv->fence_seq, dev_priv->last_read_sequence); |
| 121 | iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE); | 122 | iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE); |
| 122 | 123 | ||
| 123 | return vmw_fifo_send_fence(dev_priv, &dummy); | 124 | return vmw_fifo_send_fence(dev_priv, &dummy); |
| @@ -283,7 +284,7 @@ void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes) | |||
| 283 | uint32_t reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE; | 284 | uint32_t reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE; |
| 284 | int ret; | 285 | int ret; |
| 285 | 286 | ||
| 286 | down_write(&fifo_state->rwsem); | 287 | mutex_lock(&fifo_state->fifo_mutex); |
| 287 | max = ioread32(fifo_mem + SVGA_FIFO_MAX); | 288 | max = ioread32(fifo_mem + SVGA_FIFO_MAX); |
| 288 | min = ioread32(fifo_mem + SVGA_FIFO_MIN); | 289 | min = ioread32(fifo_mem + SVGA_FIFO_MIN); |
| 289 | next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD); | 290 | next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD); |
| @@ -351,7 +352,7 @@ void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes) | |||
| 351 | } | 352 | } |
| 352 | out_err: | 353 | out_err: |
| 353 | fifo_state->reserved_size = 0; | 354 | fifo_state->reserved_size = 0; |
| 354 | up_write(&fifo_state->rwsem); | 355 | mutex_unlock(&fifo_state->fifo_mutex); |
| 355 | return NULL; | 356 | return NULL; |
| 356 | } | 357 | } |
| 357 | 358 | ||
| @@ -426,6 +427,7 @@ void vmw_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes) | |||
| 426 | 427 | ||
| 427 | } | 428 | } |
| 428 | 429 | ||
| 430 | down_write(&fifo_state->rwsem); | ||
| 429 | if (fifo_state->using_bounce_buffer || reserveable) { | 431 | if (fifo_state->using_bounce_buffer || reserveable) { |
| 430 | next_cmd += bytes; | 432 | next_cmd += bytes; |
| 431 | if (next_cmd >= max) | 433 | if (next_cmd >= max) |
| @@ -437,8 +439,9 @@ void vmw_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes) | |||
| 437 | if (reserveable) | 439 | if (reserveable) |
| 438 | iowrite32(0, fifo_mem + SVGA_FIFO_RESERVED); | 440 | iowrite32(0, fifo_mem + SVGA_FIFO_RESERVED); |
| 439 | mb(); | 441 | mb(); |
| 440 | vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC); | ||
| 441 | up_write(&fifo_state->rwsem); | 442 | up_write(&fifo_state->rwsem); |
| 443 | vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC); | ||
| 444 | mutex_unlock(&fifo_state->fifo_mutex); | ||
| 442 | } | 445 | } |
| 443 | 446 | ||
| 444 | int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence) | 447 | int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence) |
| @@ -451,9 +454,7 @@ int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence) | |||
| 451 | 454 | ||
| 452 | fm = vmw_fifo_reserve(dev_priv, bytes); | 455 | fm = vmw_fifo_reserve(dev_priv, bytes); |
| 453 | if (unlikely(fm == NULL)) { | 456 | if (unlikely(fm == NULL)) { |
| 454 | down_write(&fifo_state->rwsem); | 457 | *sequence = atomic_read(&dev_priv->fence_seq); |
| 455 | *sequence = dev_priv->fence_seq; | ||
| 456 | up_write(&fifo_state->rwsem); | ||
| 457 | ret = -ENOMEM; | 458 | ret = -ENOMEM; |
| 458 | (void)vmw_fallback_wait(dev_priv, false, true, *sequence, | 459 | (void)vmw_fallback_wait(dev_priv, false, true, *sequence, |
| 459 | false, 3*HZ); | 460 | false, 3*HZ); |
| @@ -461,7 +462,7 @@ int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence) | |||
| 461 | } | 462 | } |
| 462 | 463 | ||
| 463 | do { | 464 | do { |
| 464 | *sequence = dev_priv->fence_seq++; | 465 | *sequence = atomic_add_return(1, &dev_priv->fence_seq); |
| 465 | } while (*sequence == 0); | 466 | } while (*sequence == 0); |
| 466 | 467 | ||
| 467 | if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE)) { | 468 | if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE)) { |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c index d40086fc8647..4d7cb5393860 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c | |||
| @@ -85,19 +85,12 @@ bool vmw_fence_signaled(struct vmw_private *dev_priv, | |||
| 85 | return true; | 85 | return true; |
| 86 | 86 | ||
| 87 | /** | 87 | /** |
| 88 | * Below is to signal stale fences that have wrapped. | ||
| 89 | * First, block fence submission. | ||
| 90 | */ | ||
| 91 | |||
| 92 | down_read(&fifo_state->rwsem); | ||
| 93 | |||
| 94 | /** | ||
| 95 | * Then check if the sequence is higher than what we've actually | 88 | * Then check if the sequence is higher than what we've actually |
| 96 | * emitted. Then the fence is stale and signaled. | 89 | * emitted. Then the fence is stale and signaled. |
| 97 | */ | 90 | */ |
| 98 | 91 | ||
| 99 | ret = ((dev_priv->fence_seq - sequence) > VMW_FENCE_WRAP); | 92 | ret = ((atomic_read(&dev_priv->fence_seq) - sequence) |
| 100 | up_read(&fifo_state->rwsem); | 93 | > VMW_FENCE_WRAP); |
| 101 | 94 | ||
| 102 | return ret; | 95 | return ret; |
| 103 | } | 96 | } |
| @@ -127,7 +120,7 @@ int vmw_fallback_wait(struct vmw_private *dev_priv, | |||
| 127 | 120 | ||
| 128 | if (fifo_idle) | 121 | if (fifo_idle) |
| 129 | down_read(&fifo_state->rwsem); | 122 | down_read(&fifo_state->rwsem); |
| 130 | signal_seq = dev_priv->fence_seq; | 123 | signal_seq = atomic_read(&dev_priv->fence_seq); |
| 131 | ret = 0; | 124 | ret = 0; |
| 132 | 125 | ||
| 133 | for (;;) { | 126 | for (;;) { |
