diff options
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 28 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 25 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 18 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 36 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 8 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_irq.c | 25 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 2 |
7 files changed, 56 insertions, 86 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 7b5d22110f25..6c6b655defcf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
| @@ -406,11 +406,9 @@ int vmw_3d_resource_inc(struct vmw_private *dev_priv, | |||
| 406 | if (unlikely(ret != 0)) | 406 | if (unlikely(ret != 0)) |
| 407 | --dev_priv->num_3d_resources; | 407 | --dev_priv->num_3d_resources; |
| 408 | } else if (unhide_svga) { | 408 | } else if (unhide_svga) { |
| 409 | mutex_lock(&dev_priv->hw_mutex); | ||
| 410 | vmw_write(dev_priv, SVGA_REG_ENABLE, | 409 | vmw_write(dev_priv, SVGA_REG_ENABLE, |
| 411 | vmw_read(dev_priv, SVGA_REG_ENABLE) & | 410 | vmw_read(dev_priv, SVGA_REG_ENABLE) & |
| 412 | ~SVGA_REG_ENABLE_HIDE); | 411 | ~SVGA_REG_ENABLE_HIDE); |
| 413 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 414 | } | 412 | } |
| 415 | 413 | ||
| 416 | mutex_unlock(&dev_priv->release_mutex); | 414 | mutex_unlock(&dev_priv->release_mutex); |
| @@ -433,13 +431,10 @@ void vmw_3d_resource_dec(struct vmw_private *dev_priv, | |||
| 433 | mutex_lock(&dev_priv->release_mutex); | 431 | mutex_lock(&dev_priv->release_mutex); |
| 434 | if (unlikely(--dev_priv->num_3d_resources == 0)) | 432 | if (unlikely(--dev_priv->num_3d_resources == 0)) |
| 435 | vmw_release_device(dev_priv); | 433 | vmw_release_device(dev_priv); |
| 436 | else if (hide_svga) { | 434 | else if (hide_svga) |
| 437 | mutex_lock(&dev_priv->hw_mutex); | ||
| 438 | vmw_write(dev_priv, SVGA_REG_ENABLE, | 435 | vmw_write(dev_priv, SVGA_REG_ENABLE, |
| 439 | vmw_read(dev_priv, SVGA_REG_ENABLE) | | 436 | vmw_read(dev_priv, SVGA_REG_ENABLE) | |
| 440 | SVGA_REG_ENABLE_HIDE); | 437 | SVGA_REG_ENABLE_HIDE); |
| 441 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 442 | } | ||
| 443 | 438 | ||
| 444 | n3d = (int32_t) dev_priv->num_3d_resources; | 439 | n3d = (int32_t) dev_priv->num_3d_resources; |
| 445 | mutex_unlock(&dev_priv->release_mutex); | 440 | mutex_unlock(&dev_priv->release_mutex); |
| @@ -600,12 +595,14 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
| 600 | dev_priv->dev = dev; | 595 | dev_priv->dev = dev; |
| 601 | dev_priv->vmw_chipset = chipset; | 596 | dev_priv->vmw_chipset = chipset; |
| 602 | dev_priv->last_read_seqno = (uint32_t) -100; | 597 | dev_priv->last_read_seqno = (uint32_t) -100; |
| 603 | mutex_init(&dev_priv->hw_mutex); | ||
| 604 | mutex_init(&dev_priv->cmdbuf_mutex); | 598 | mutex_init(&dev_priv->cmdbuf_mutex); |
| 605 | mutex_init(&dev_priv->release_mutex); | 599 | mutex_init(&dev_priv->release_mutex); |
| 606 | mutex_init(&dev_priv->binding_mutex); | 600 | mutex_init(&dev_priv->binding_mutex); |
| 607 | rwlock_init(&dev_priv->resource_lock); | 601 | rwlock_init(&dev_priv->resource_lock); |
| 608 | ttm_lock_init(&dev_priv->reservation_sem); | 602 | ttm_lock_init(&dev_priv->reservation_sem); |
| 603 | spin_lock_init(&dev_priv->hw_lock); | ||
| 604 | spin_lock_init(&dev_priv->waiter_lock); | ||
| 605 | spin_lock_init(&dev_priv->cap_lock); | ||
| 609 | 606 | ||
| 610 | for (i = vmw_res_context; i < vmw_res_max; ++i) { | 607 | for (i = vmw_res_context; i < vmw_res_max; ++i) { |
| 611 | idr_init(&dev_priv->res_idr[i]); | 608 | idr_init(&dev_priv->res_idr[i]); |
| @@ -626,14 +623,11 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
| 626 | 623 | ||
| 627 | dev_priv->enable_fb = enable_fbdev; | 624 | dev_priv->enable_fb = enable_fbdev; |
| 628 | 625 | ||
| 629 | mutex_lock(&dev_priv->hw_mutex); | ||
| 630 | |||
| 631 | vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); | 626 | vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); |
| 632 | svga_id = vmw_read(dev_priv, SVGA_REG_ID); | 627 | svga_id = vmw_read(dev_priv, SVGA_REG_ID); |
| 633 | if (svga_id != SVGA_ID_2) { | 628 | if (svga_id != SVGA_ID_2) { |
| 634 | ret = -ENOSYS; | 629 | ret = -ENOSYS; |
| 635 | DRM_ERROR("Unsupported SVGA ID 0x%x\n", svga_id); | 630 | DRM_ERROR("Unsupported SVGA ID 0x%x\n", svga_id); |
| 636 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 637 | goto out_err0; | 631 | goto out_err0; |
| 638 | } | 632 | } |
| 639 | 633 | ||
| @@ -683,10 +677,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
| 683 | dev_priv->prim_bb_mem = dev_priv->vram_size; | 677 | dev_priv->prim_bb_mem = dev_priv->vram_size; |
| 684 | 678 | ||
| 685 | ret = vmw_dma_masks(dev_priv); | 679 | ret = vmw_dma_masks(dev_priv); |
| 686 | if (unlikely(ret != 0)) { | 680 | if (unlikely(ret != 0)) |
| 687 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 688 | goto out_err0; | 681 | goto out_err0; |
| 689 | } | ||
| 690 | 682 | ||
| 691 | /* | 683 | /* |
| 692 | * Limit back buffer size to VRAM size. Remove this once | 684 | * Limit back buffer size to VRAM size. Remove this once |
| @@ -695,8 +687,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
| 695 | if (dev_priv->prim_bb_mem > dev_priv->vram_size) | 687 | if (dev_priv->prim_bb_mem > dev_priv->vram_size) |
| 696 | dev_priv->prim_bb_mem = dev_priv->vram_size; | 688 | dev_priv->prim_bb_mem = dev_priv->vram_size; |
| 697 | 689 | ||
| 698 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 699 | |||
| 700 | vmw_print_capabilities(dev_priv->capabilities); | 690 | vmw_print_capabilities(dev_priv->capabilities); |
| 701 | 691 | ||
| 702 | if (dev_priv->capabilities & SVGA_CAP_GMR2) { | 692 | if (dev_priv->capabilities & SVGA_CAP_GMR2) { |
| @@ -1160,9 +1150,7 @@ static int vmw_master_set(struct drm_device *dev, | |||
| 1160 | if (unlikely(ret != 0)) | 1150 | if (unlikely(ret != 0)) |
| 1161 | return ret; | 1151 | return ret; |
| 1162 | vmw_kms_save_vga(dev_priv); | 1152 | vmw_kms_save_vga(dev_priv); |
| 1163 | mutex_lock(&dev_priv->hw_mutex); | ||
| 1164 | vmw_write(dev_priv, SVGA_REG_TRACES, 0); | 1153 | vmw_write(dev_priv, SVGA_REG_TRACES, 0); |
| 1165 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 1166 | } | 1154 | } |
| 1167 | 1155 | ||
| 1168 | if (active) { | 1156 | if (active) { |
| @@ -1196,9 +1184,7 @@ out_no_active_lock: | |||
| 1196 | if (!dev_priv->enable_fb) { | 1184 | if (!dev_priv->enable_fb) { |
| 1197 | vmw_kms_restore_vga(dev_priv); | 1185 | vmw_kms_restore_vga(dev_priv); |
| 1198 | vmw_3d_resource_dec(dev_priv, true); | 1186 | vmw_3d_resource_dec(dev_priv, true); |
| 1199 | mutex_lock(&dev_priv->hw_mutex); | ||
| 1200 | vmw_write(dev_priv, SVGA_REG_TRACES, 1); | 1187 | vmw_write(dev_priv, SVGA_REG_TRACES, 1); |
| 1201 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 1202 | } | 1188 | } |
| 1203 | return ret; | 1189 | return ret; |
| 1204 | } | 1190 | } |
| @@ -1233,9 +1219,7 @@ static void vmw_master_drop(struct drm_device *dev, | |||
| 1233 | DRM_ERROR("Unable to clean VRAM on master drop.\n"); | 1219 | DRM_ERROR("Unable to clean VRAM on master drop.\n"); |
| 1234 | vmw_kms_restore_vga(dev_priv); | 1220 | vmw_kms_restore_vga(dev_priv); |
| 1235 | vmw_3d_resource_dec(dev_priv, true); | 1221 | vmw_3d_resource_dec(dev_priv, true); |
| 1236 | mutex_lock(&dev_priv->hw_mutex); | ||
| 1237 | vmw_write(dev_priv, SVGA_REG_TRACES, 1); | 1222 | vmw_write(dev_priv, SVGA_REG_TRACES, 1); |
| 1238 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 1239 | } | 1223 | } |
| 1240 | 1224 | ||
| 1241 | dev_priv->active_master = &dev_priv->fbdev_master; | 1225 | dev_priv->active_master = &dev_priv->fbdev_master; |
| @@ -1367,10 +1351,8 @@ static void vmw_pm_complete(struct device *kdev) | |||
| 1367 | struct drm_device *dev = pci_get_drvdata(pdev); | 1351 | struct drm_device *dev = pci_get_drvdata(pdev); |
| 1368 | struct vmw_private *dev_priv = vmw_priv(dev); | 1352 | struct vmw_private *dev_priv = vmw_priv(dev); |
| 1369 | 1353 | ||
| 1370 | mutex_lock(&dev_priv->hw_mutex); | ||
| 1371 | vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); | 1354 | vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); |
| 1372 | (void) vmw_read(dev_priv, SVGA_REG_ID); | 1355 | (void) vmw_read(dev_priv, SVGA_REG_ID); |
| 1373 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 1374 | 1356 | ||
| 1375 | /** | 1357 | /** |
| 1376 | * Reclaim 3d reference held by fbdev and potentially | 1358 | * Reclaim 3d reference held by fbdev and potentially |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 4ee799b43d5d..d26a6daa9719 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | |||
| @@ -399,7 +399,8 @@ struct vmw_private { | |||
| 399 | uint32_t memory_size; | 399 | uint32_t memory_size; |
| 400 | bool has_gmr; | 400 | bool has_gmr; |
| 401 | bool has_mob; | 401 | bool has_mob; |
| 402 | struct mutex hw_mutex; | 402 | spinlock_t hw_lock; |
| 403 | spinlock_t cap_lock; | ||
| 403 | 404 | ||
| 404 | /* | 405 | /* |
| 405 | * VGA registers. | 406 | * VGA registers. |
| @@ -449,8 +450,9 @@ struct vmw_private { | |||
| 449 | atomic_t marker_seq; | 450 | atomic_t marker_seq; |
| 450 | wait_queue_head_t fence_queue; | 451 | wait_queue_head_t fence_queue; |
| 451 | wait_queue_head_t fifo_queue; | 452 | wait_queue_head_t fifo_queue; |
| 452 | int fence_queue_waiters; /* Protected by hw_mutex */ | 453 | spinlock_t waiter_lock; |
| 453 | int goal_queue_waiters; /* Protected by hw_mutex */ | 454 | int fence_queue_waiters; /* Protected by waiter_lock */ |
| 455 | int goal_queue_waiters; /* Protected by waiter_lock */ | ||
| 454 | atomic_t fifo_queue_waiters; | 456 | atomic_t fifo_queue_waiters; |
| 455 | uint32_t last_read_seqno; | 457 | uint32_t last_read_seqno; |
| 456 | spinlock_t irq_lock; | 458 | spinlock_t irq_lock; |
| @@ -553,20 +555,35 @@ static inline struct vmw_master *vmw_master(struct drm_master *master) | |||
| 553 | return (struct vmw_master *) master->driver_priv; | 555 | return (struct vmw_master *) master->driver_priv; |
| 554 | } | 556 | } |
| 555 | 557 | ||
| 558 | /* | ||
| 559 | * The locking here is fine-grained, so that it is performed once | ||
| 560 | * for every read- and write operation. This is of course costly, but we | ||
| 561 | * don't perform much register access in the timing critical paths anyway. | ||
| 562 | * Instead we have the extra benefit of being sure that we don't forget | ||
| 563 | * the hw lock around register accesses. | ||
| 564 | */ | ||
| 556 | static inline void vmw_write(struct vmw_private *dev_priv, | 565 | static inline void vmw_write(struct vmw_private *dev_priv, |
| 557 | unsigned int offset, uint32_t value) | 566 | unsigned int offset, uint32_t value) |
| 558 | { | 567 | { |
| 568 | unsigned long irq_flags; | ||
| 569 | |||
| 570 | spin_lock_irqsave(&dev_priv->hw_lock, irq_flags); | ||
| 559 | outl(offset, dev_priv->io_start + VMWGFX_INDEX_PORT); | 571 | outl(offset, dev_priv->io_start + VMWGFX_INDEX_PORT); |
| 560 | outl(value, dev_priv->io_start + VMWGFX_VALUE_PORT); | 572 | outl(value, dev_priv->io_start + VMWGFX_VALUE_PORT); |
| 573 | spin_unlock_irqrestore(&dev_priv->hw_lock, irq_flags); | ||
| 561 | } | 574 | } |
| 562 | 575 | ||
| 563 | static inline uint32_t vmw_read(struct vmw_private *dev_priv, | 576 | static inline uint32_t vmw_read(struct vmw_private *dev_priv, |
| 564 | unsigned int offset) | 577 | unsigned int offset) |
| 565 | { | 578 | { |
| 566 | uint32_t val; | 579 | unsigned long irq_flags; |
| 580 | u32 val; | ||
| 567 | 581 | ||
| 582 | spin_lock_irqsave(&dev_priv->hw_lock, irq_flags); | ||
| 568 | outl(offset, dev_priv->io_start + VMWGFX_INDEX_PORT); | 583 | outl(offset, dev_priv->io_start + VMWGFX_INDEX_PORT); |
| 569 | val = inl(dev_priv->io_start + VMWGFX_VALUE_PORT); | 584 | val = inl(dev_priv->io_start + VMWGFX_VALUE_PORT); |
| 585 | spin_unlock_irqrestore(&dev_priv->hw_lock, irq_flags); | ||
| 586 | |||
| 570 | return val; | 587 | return val; |
| 571 | } | 588 | } |
| 572 | 589 | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index b7594cb758af..945f1e0dad92 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | |||
| @@ -35,7 +35,7 @@ struct vmw_fence_manager { | |||
| 35 | struct vmw_private *dev_priv; | 35 | struct vmw_private *dev_priv; |
| 36 | spinlock_t lock; | 36 | spinlock_t lock; |
| 37 | struct list_head fence_list; | 37 | struct list_head fence_list; |
| 38 | struct work_struct work, ping_work; | 38 | struct work_struct work; |
| 39 | u32 user_fence_size; | 39 | u32 user_fence_size; |
| 40 | u32 fence_size; | 40 | u32 fence_size; |
| 41 | u32 event_fence_action_size; | 41 | u32 event_fence_action_size; |
| @@ -134,14 +134,6 @@ static const char *vmw_fence_get_timeline_name(struct fence *f) | |||
| 134 | return "svga"; | 134 | return "svga"; |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | static void vmw_fence_ping_func(struct work_struct *work) | ||
| 138 | { | ||
| 139 | struct vmw_fence_manager *fman = | ||
| 140 | container_of(work, struct vmw_fence_manager, ping_work); | ||
| 141 | |||
| 142 | vmw_fifo_ping_host(fman->dev_priv, SVGA_SYNC_GENERIC); | ||
| 143 | } | ||
| 144 | |||
| 145 | static bool vmw_fence_enable_signaling(struct fence *f) | 137 | static bool vmw_fence_enable_signaling(struct fence *f) |
| 146 | { | 138 | { |
| 147 | struct vmw_fence_obj *fence = | 139 | struct vmw_fence_obj *fence = |
| @@ -155,11 +147,7 @@ static bool vmw_fence_enable_signaling(struct fence *f) | |||
| 155 | if (seqno - fence->base.seqno < VMW_FENCE_WRAP) | 147 | if (seqno - fence->base.seqno < VMW_FENCE_WRAP) |
| 156 | return false; | 148 | return false; |
| 157 | 149 | ||
| 158 | if (mutex_trylock(&dev_priv->hw_mutex)) { | 150 | vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC); |
| 159 | vmw_fifo_ping_host_locked(dev_priv, SVGA_SYNC_GENERIC); | ||
| 160 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 161 | } else | ||
| 162 | schedule_work(&fman->ping_work); | ||
| 163 | 151 | ||
| 164 | return true; | 152 | return true; |
| 165 | } | 153 | } |
| @@ -305,7 +293,6 @@ struct vmw_fence_manager *vmw_fence_manager_init(struct vmw_private *dev_priv) | |||
| 305 | INIT_LIST_HEAD(&fman->fence_list); | 293 | INIT_LIST_HEAD(&fman->fence_list); |
| 306 | INIT_LIST_HEAD(&fman->cleanup_list); | 294 | INIT_LIST_HEAD(&fman->cleanup_list); |
| 307 | INIT_WORK(&fman->work, &vmw_fence_work_func); | 295 | INIT_WORK(&fman->work, &vmw_fence_work_func); |
| 308 | INIT_WORK(&fman->ping_work, &vmw_fence_ping_func); | ||
| 309 | fman->fifo_down = true; | 296 | fman->fifo_down = true; |
| 310 | fman->user_fence_size = ttm_round_pot(sizeof(struct vmw_user_fence)); | 297 | fman->user_fence_size = ttm_round_pot(sizeof(struct vmw_user_fence)); |
| 311 | fman->fence_size = ttm_round_pot(sizeof(struct vmw_fence_obj)); | 298 | fman->fence_size = ttm_round_pot(sizeof(struct vmw_fence_obj)); |
| @@ -323,7 +310,6 @@ void vmw_fence_manager_takedown(struct vmw_fence_manager *fman) | |||
| 323 | bool lists_empty; | 310 | bool lists_empty; |
| 324 | 311 | ||
| 325 | (void) cancel_work_sync(&fman->work); | 312 | (void) cancel_work_sync(&fman->work); |
| 326 | (void) cancel_work_sync(&fman->ping_work); | ||
| 327 | 313 | ||
| 328 | spin_lock_irqsave(&fman->lock, irq_flags); | 314 | spin_lock_irqsave(&fman->lock, irq_flags); |
| 329 | lists_empty = list_empty(&fman->fence_list) && | 315 | lists_empty = list_empty(&fman->fence_list) && |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index 09e10aefcd8e..39f2b03888e7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | |||
| @@ -44,10 +44,10 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv) | |||
| 44 | if (!dev_priv->has_mob) | 44 | if (!dev_priv->has_mob) |
| 45 | return false; | 45 | return false; |
| 46 | 46 | ||
| 47 | mutex_lock(&dev_priv->hw_mutex); | 47 | spin_lock(&dev_priv->cap_lock); |
| 48 | vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_3D); | 48 | vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_3D); |
| 49 | result = vmw_read(dev_priv, SVGA_REG_DEV_CAP); | 49 | result = vmw_read(dev_priv, SVGA_REG_DEV_CAP); |
| 50 | mutex_unlock(&dev_priv->hw_mutex); | 50 | spin_unlock(&dev_priv->cap_lock); |
| 51 | 51 | ||
| 52 | return (result != 0); | 52 | return (result != 0); |
| 53 | } | 53 | } |
| @@ -120,7 +120,6 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | |||
| 120 | DRM_INFO("height %d\n", vmw_read(dev_priv, SVGA_REG_HEIGHT)); | 120 | DRM_INFO("height %d\n", vmw_read(dev_priv, SVGA_REG_HEIGHT)); |
| 121 | DRM_INFO("bpp %d\n", vmw_read(dev_priv, SVGA_REG_BITS_PER_PIXEL)); | 121 | DRM_INFO("bpp %d\n", vmw_read(dev_priv, SVGA_REG_BITS_PER_PIXEL)); |
| 122 | 122 | ||
| 123 | mutex_lock(&dev_priv->hw_mutex); | ||
| 124 | dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE); | 123 | dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE); |
| 125 | dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE); | 124 | dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE); |
| 126 | dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES); | 125 | dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES); |
| @@ -143,7 +142,6 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | |||
| 143 | mb(); | 142 | mb(); |
| 144 | 143 | ||
| 145 | vmw_write(dev_priv, SVGA_REG_CONFIG_DONE, 1); | 144 | vmw_write(dev_priv, SVGA_REG_CONFIG_DONE, 1); |
| 146 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 147 | 145 | ||
| 148 | max = ioread32(fifo_mem + SVGA_FIFO_MAX); | 146 | max = ioread32(fifo_mem + SVGA_FIFO_MAX); |
| 149 | min = ioread32(fifo_mem + SVGA_FIFO_MIN); | 147 | min = ioread32(fifo_mem + SVGA_FIFO_MIN); |
| @@ -160,31 +158,28 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | |||
| 160 | return vmw_fifo_send_fence(dev_priv, &dummy); | 158 | return vmw_fifo_send_fence(dev_priv, &dummy); |
| 161 | } | 159 | } |
| 162 | 160 | ||
| 163 | void vmw_fifo_ping_host_locked(struct vmw_private *dev_priv, uint32_t reason) | 161 | void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason) |
| 164 | { | 162 | { |
| 165 | __le32 __iomem *fifo_mem = dev_priv->mmio_virt; | 163 | __le32 __iomem *fifo_mem = dev_priv->mmio_virt; |
| 164 | static DEFINE_SPINLOCK(ping_lock); | ||
| 165 | unsigned long irq_flags; | ||
| 166 | 166 | ||
| 167 | /* | ||
| 168 | * The ping_lock is needed because we don't have an atomic | ||
| 169 | * test-and-set of the SVGA_FIFO_BUSY register. | ||
| 170 | */ | ||
| 171 | spin_lock_irqsave(&ping_lock, irq_flags); | ||
| 167 | if (unlikely(ioread32(fifo_mem + SVGA_FIFO_BUSY) == 0)) { | 172 | if (unlikely(ioread32(fifo_mem + SVGA_FIFO_BUSY) == 0)) { |
| 168 | iowrite32(1, fifo_mem + SVGA_FIFO_BUSY); | 173 | iowrite32(1, fifo_mem + SVGA_FIFO_BUSY); |
| 169 | vmw_write(dev_priv, SVGA_REG_SYNC, reason); | 174 | vmw_write(dev_priv, SVGA_REG_SYNC, reason); |
| 170 | } | 175 | } |
| 171 | } | 176 | spin_unlock_irqrestore(&ping_lock, irq_flags); |
| 172 | |||
| 173 | void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason) | ||
| 174 | { | ||
| 175 | mutex_lock(&dev_priv->hw_mutex); | ||
| 176 | |||
| 177 | vmw_fifo_ping_host_locked(dev_priv, reason); | ||
| 178 | |||
| 179 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 180 | } | 177 | } |
| 181 | 178 | ||
| 182 | void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | 179 | void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) |
| 183 | { | 180 | { |
| 184 | __le32 __iomem *fifo_mem = dev_priv->mmio_virt; | 181 | __le32 __iomem *fifo_mem = dev_priv->mmio_virt; |
| 185 | 182 | ||
| 186 | mutex_lock(&dev_priv->hw_mutex); | ||
| 187 | |||
| 188 | vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC); | 183 | vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC); |
| 189 | while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0) | 184 | while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0) |
| 190 | ; | 185 | ; |
| @@ -198,7 +193,6 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | |||
| 198 | vmw_write(dev_priv, SVGA_REG_TRACES, | 193 | vmw_write(dev_priv, SVGA_REG_TRACES, |
| 199 | dev_priv->traces_state); | 194 | dev_priv->traces_state); |
| 200 | 195 | ||
| 201 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 202 | vmw_marker_queue_takedown(&fifo->marker_queue); | 196 | vmw_marker_queue_takedown(&fifo->marker_queue); |
| 203 | 197 | ||
| 204 | if (likely(fifo->static_buffer != NULL)) { | 198 | if (likely(fifo->static_buffer != NULL)) { |
| @@ -271,7 +265,7 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv, | |||
| 271 | return vmw_fifo_wait_noirq(dev_priv, bytes, | 265 | return vmw_fifo_wait_noirq(dev_priv, bytes, |
| 272 | interruptible, timeout); | 266 | interruptible, timeout); |
| 273 | 267 | ||
| 274 | mutex_lock(&dev_priv->hw_mutex); | 268 | spin_lock(&dev_priv->waiter_lock); |
| 275 | if (atomic_add_return(1, &dev_priv->fifo_queue_waiters) > 0) { | 269 | if (atomic_add_return(1, &dev_priv->fifo_queue_waiters) > 0) { |
| 276 | spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); | 270 | spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); |
| 277 | outl(SVGA_IRQFLAG_FIFO_PROGRESS, | 271 | outl(SVGA_IRQFLAG_FIFO_PROGRESS, |
| @@ -280,7 +274,7 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv, | |||
| 280 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | 274 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); |
| 281 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | 275 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); |
| 282 | } | 276 | } |
| 283 | mutex_unlock(&dev_priv->hw_mutex); | 277 | spin_unlock(&dev_priv->waiter_lock); |
| 284 | 278 | ||
| 285 | if (interruptible) | 279 | if (interruptible) |
| 286 | ret = wait_event_interruptible_timeout | 280 | ret = wait_event_interruptible_timeout |
| @@ -296,14 +290,14 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv, | |||
| 296 | else if (likely(ret > 0)) | 290 | else if (likely(ret > 0)) |
| 297 | ret = 0; | 291 | ret = 0; |
| 298 | 292 | ||
| 299 | mutex_lock(&dev_priv->hw_mutex); | 293 | spin_lock(&dev_priv->waiter_lock); |
| 300 | if (atomic_dec_and_test(&dev_priv->fifo_queue_waiters)) { | 294 | if (atomic_dec_and_test(&dev_priv->fifo_queue_waiters)) { |
| 301 | spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); | 295 | spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); |
| 302 | dev_priv->irq_mask &= ~SVGA_IRQFLAG_FIFO_PROGRESS; | 296 | dev_priv->irq_mask &= ~SVGA_IRQFLAG_FIFO_PROGRESS; |
| 303 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | 297 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); |
| 304 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | 298 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); |
| 305 | } | 299 | } |
| 306 | mutex_unlock(&dev_priv->hw_mutex); | 300 | spin_unlock(&dev_priv->waiter_lock); |
| 307 | 301 | ||
| 308 | return ret; | 302 | return ret; |
| 309 | } | 303 | } |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index 37881ecf5d7a..69c8ce23123c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | |||
| @@ -135,13 +135,13 @@ static int vmw_fill_compat_cap(struct vmw_private *dev_priv, void *bounce, | |||
| 135 | (pair_offset + max_size * sizeof(SVGA3dCapPair)) / sizeof(u32); | 135 | (pair_offset + max_size * sizeof(SVGA3dCapPair)) / sizeof(u32); |
| 136 | compat_cap->header.type = SVGA3DCAPS_RECORD_DEVCAPS; | 136 | compat_cap->header.type = SVGA3DCAPS_RECORD_DEVCAPS; |
| 137 | 137 | ||
| 138 | mutex_lock(&dev_priv->hw_mutex); | 138 | spin_lock(&dev_priv->cap_lock); |
| 139 | for (i = 0; i < max_size; ++i) { | 139 | for (i = 0; i < max_size; ++i) { |
| 140 | vmw_write(dev_priv, SVGA_REG_DEV_CAP, i); | 140 | vmw_write(dev_priv, SVGA_REG_DEV_CAP, i); |
| 141 | compat_cap->pairs[i][0] = i; | 141 | compat_cap->pairs[i][0] = i; |
| 142 | compat_cap->pairs[i][1] = vmw_read(dev_priv, SVGA_REG_DEV_CAP); | 142 | compat_cap->pairs[i][1] = vmw_read(dev_priv, SVGA_REG_DEV_CAP); |
| 143 | } | 143 | } |
| 144 | mutex_unlock(&dev_priv->hw_mutex); | 144 | spin_unlock(&dev_priv->cap_lock); |
| 145 | 145 | ||
| 146 | return 0; | 146 | return 0; |
| 147 | } | 147 | } |
| @@ -191,12 +191,12 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data, | |||
| 191 | if (num > SVGA3D_DEVCAP_MAX) | 191 | if (num > SVGA3D_DEVCAP_MAX) |
| 192 | num = SVGA3D_DEVCAP_MAX; | 192 | num = SVGA3D_DEVCAP_MAX; |
| 193 | 193 | ||
| 194 | mutex_lock(&dev_priv->hw_mutex); | 194 | spin_lock(&dev_priv->cap_lock); |
| 195 | for (i = 0; i < num; ++i) { | 195 | for (i = 0; i < num; ++i) { |
| 196 | vmw_write(dev_priv, SVGA_REG_DEV_CAP, i); | 196 | vmw_write(dev_priv, SVGA_REG_DEV_CAP, i); |
| 197 | *bounce32++ = vmw_read(dev_priv, SVGA_REG_DEV_CAP); | 197 | *bounce32++ = vmw_read(dev_priv, SVGA_REG_DEV_CAP); |
| 198 | } | 198 | } |
| 199 | mutex_unlock(&dev_priv->hw_mutex); | 199 | spin_unlock(&dev_priv->cap_lock); |
| 200 | } else if (gb_objects) { | 200 | } else if (gb_objects) { |
| 201 | ret = vmw_fill_compat_cap(dev_priv, bounce, size); | 201 | ret = vmw_fill_compat_cap(dev_priv, bounce, size); |
| 202 | if (unlikely(ret != 0)) | 202 | if (unlikely(ret != 0)) |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c index 0c423766c441..9fe9827ee499 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c | |||
| @@ -62,13 +62,8 @@ irqreturn_t vmw_irq_handler(int irq, void *arg) | |||
| 62 | 62 | ||
| 63 | static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t seqno) | 63 | static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t seqno) |
| 64 | { | 64 | { |
| 65 | uint32_t busy; | ||
| 66 | 65 | ||
| 67 | mutex_lock(&dev_priv->hw_mutex); | 66 | return (vmw_read(dev_priv, SVGA_REG_BUSY) == 0); |
| 68 | busy = vmw_read(dev_priv, SVGA_REG_BUSY); | ||
| 69 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 70 | |||
| 71 | return (busy == 0); | ||
| 72 | } | 67 | } |
| 73 | 68 | ||
| 74 | void vmw_update_seqno(struct vmw_private *dev_priv, | 69 | void vmw_update_seqno(struct vmw_private *dev_priv, |
| @@ -184,7 +179,7 @@ int vmw_fallback_wait(struct vmw_private *dev_priv, | |||
| 184 | 179 | ||
| 185 | void vmw_seqno_waiter_add(struct vmw_private *dev_priv) | 180 | void vmw_seqno_waiter_add(struct vmw_private *dev_priv) |
| 186 | { | 181 | { |
| 187 | mutex_lock(&dev_priv->hw_mutex); | 182 | spin_lock(&dev_priv->waiter_lock); |
| 188 | if (dev_priv->fence_queue_waiters++ == 0) { | 183 | if (dev_priv->fence_queue_waiters++ == 0) { |
| 189 | unsigned long irq_flags; | 184 | unsigned long irq_flags; |
| 190 | 185 | ||
| @@ -195,12 +190,12 @@ void vmw_seqno_waiter_add(struct vmw_private *dev_priv) | |||
| 195 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | 190 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); |
| 196 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | 191 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); |
| 197 | } | 192 | } |
| 198 | mutex_unlock(&dev_priv->hw_mutex); | 193 | spin_unlock(&dev_priv->waiter_lock); |
| 199 | } | 194 | } |
| 200 | 195 | ||
| 201 | void vmw_seqno_waiter_remove(struct vmw_private *dev_priv) | 196 | void vmw_seqno_waiter_remove(struct vmw_private *dev_priv) |
| 202 | { | 197 | { |
| 203 | mutex_lock(&dev_priv->hw_mutex); | 198 | spin_lock(&dev_priv->waiter_lock); |
| 204 | if (--dev_priv->fence_queue_waiters == 0) { | 199 | if (--dev_priv->fence_queue_waiters == 0) { |
| 205 | unsigned long irq_flags; | 200 | unsigned long irq_flags; |
| 206 | 201 | ||
| @@ -209,13 +204,13 @@ void vmw_seqno_waiter_remove(struct vmw_private *dev_priv) | |||
| 209 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | 204 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); |
| 210 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | 205 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); |
| 211 | } | 206 | } |
| 212 | mutex_unlock(&dev_priv->hw_mutex); | 207 | spin_unlock(&dev_priv->waiter_lock); |
| 213 | } | 208 | } |
| 214 | 209 | ||
| 215 | 210 | ||
| 216 | void vmw_goal_waiter_add(struct vmw_private *dev_priv) | 211 | void vmw_goal_waiter_add(struct vmw_private *dev_priv) |
| 217 | { | 212 | { |
| 218 | mutex_lock(&dev_priv->hw_mutex); | 213 | spin_lock(&dev_priv->waiter_lock); |
| 219 | if (dev_priv->goal_queue_waiters++ == 0) { | 214 | if (dev_priv->goal_queue_waiters++ == 0) { |
| 220 | unsigned long irq_flags; | 215 | unsigned long irq_flags; |
| 221 | 216 | ||
| @@ -226,12 +221,12 @@ void vmw_goal_waiter_add(struct vmw_private *dev_priv) | |||
| 226 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | 221 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); |
| 227 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | 222 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); |
| 228 | } | 223 | } |
| 229 | mutex_unlock(&dev_priv->hw_mutex); | 224 | spin_unlock(&dev_priv->waiter_lock); |
| 230 | } | 225 | } |
| 231 | 226 | ||
| 232 | void vmw_goal_waiter_remove(struct vmw_private *dev_priv) | 227 | void vmw_goal_waiter_remove(struct vmw_private *dev_priv) |
| 233 | { | 228 | { |
| 234 | mutex_lock(&dev_priv->hw_mutex); | 229 | spin_lock(&dev_priv->waiter_lock); |
| 235 | if (--dev_priv->goal_queue_waiters == 0) { | 230 | if (--dev_priv->goal_queue_waiters == 0) { |
| 236 | unsigned long irq_flags; | 231 | unsigned long irq_flags; |
| 237 | 232 | ||
| @@ -240,7 +235,7 @@ void vmw_goal_waiter_remove(struct vmw_private *dev_priv) | |||
| 240 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | 235 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); |
| 241 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | 236 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); |
| 242 | } | 237 | } |
| 243 | mutex_unlock(&dev_priv->hw_mutex); | 238 | spin_unlock(&dev_priv->waiter_lock); |
| 244 | } | 239 | } |
| 245 | 240 | ||
| 246 | int vmw_wait_seqno(struct vmw_private *dev_priv, | 241 | int vmw_wait_seqno(struct vmw_private *dev_priv, |
| @@ -315,9 +310,7 @@ void vmw_irq_uninstall(struct drm_device *dev) | |||
| 315 | if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK)) | 310 | if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK)) |
| 316 | return; | 311 | return; |
| 317 | 312 | ||
| 318 | mutex_lock(&dev_priv->hw_mutex); | ||
| 319 | vmw_write(dev_priv, SVGA_REG_IRQMASK, 0); | 313 | vmw_write(dev_priv, SVGA_REG_IRQMASK, 0); |
| 320 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 321 | 314 | ||
| 322 | status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); | 315 | status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); |
| 323 | outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); | 316 | outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 3725b521d931..8725b79e7847 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
| @@ -1828,9 +1828,7 @@ vmw_du_connector_detect(struct drm_connector *connector, bool force) | |||
| 1828 | struct vmw_private *dev_priv = vmw_priv(dev); | 1828 | struct vmw_private *dev_priv = vmw_priv(dev); |
| 1829 | struct vmw_display_unit *du = vmw_connector_to_du(connector); | 1829 | struct vmw_display_unit *du = vmw_connector_to_du(connector); |
| 1830 | 1830 | ||
| 1831 | mutex_lock(&dev_priv->hw_mutex); | ||
| 1832 | num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS); | 1831 | num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS); |
| 1833 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 1834 | 1832 | ||
| 1835 | return ((vmw_connector_to_du(connector)->unit < num_displays && | 1833 | return ((vmw_connector_to_du(connector)->unit < num_displays && |
| 1836 | du->pref_active) ? | 1834 | du->pref_active) ? |
