diff options
author | Dave Airlie <airlied@gmail.com> | 2015-11-07 02:16:29 -0500 |
---|---|---|
committer | Dave Airlie <airlied@gmail.com> | 2015-11-07 02:16:29 -0500 |
commit | d0baf9218cacd9dd606c75f9961f94172b16de12 (patch) | |
tree | bf52d15748429f88177d44fd404d76523c784952 | |
parent | e02328f47bd75fde9decf9657ec7d769b370f857 (diff) | |
parent | d2e8851a909c76c6f0b34553f2c9993808bc1d58 (diff) |
Merge branch 'vmwgfx-next' of git://people.freedesktop.org/~thomash/linux into drm-next
One is fix for a regression in 4.3, One irq locking rework.
* 'vmwgfx-next' of git://people.freedesktop.org/~thomash/linux:
drm/vmwgfx: Relax irq locking somewhat
drm/vmwgfx: Properly flush cursor updates and page-flips
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 23 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_irq.c | 104 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 2 |
6 files changed, 42 insertions, 100 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index d1c34aba7abd..a09cf8529b9f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
@@ -643,7 +643,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
643 | init_waitqueue_head(&dev_priv->fence_queue); | 643 | init_waitqueue_head(&dev_priv->fence_queue); |
644 | init_waitqueue_head(&dev_priv->fifo_queue); | 644 | init_waitqueue_head(&dev_priv->fifo_queue); |
645 | dev_priv->fence_queue_waiters = 0; | 645 | dev_priv->fence_queue_waiters = 0; |
646 | atomic_set(&dev_priv->fifo_queue_waiters, 0); | 646 | dev_priv->fifo_queue_waiters = 0; |
647 | 647 | ||
648 | dev_priv->used_memory_size = 0; | 648 | dev_priv->used_memory_size = 0; |
649 | 649 | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 198c8b1a81e2..a8ae9dfb83b7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | |||
@@ -440,13 +440,12 @@ struct vmw_private { | |||
440 | spinlock_t waiter_lock; | 440 | spinlock_t waiter_lock; |
441 | int fence_queue_waiters; /* Protected by waiter_lock */ | 441 | int fence_queue_waiters; /* Protected by waiter_lock */ |
442 | int goal_queue_waiters; /* Protected by waiter_lock */ | 442 | int goal_queue_waiters; /* Protected by waiter_lock */ |
443 | int cmdbuf_waiters; /* Protected by irq_lock */ | 443 | int cmdbuf_waiters; /* Protected by waiter_lock */ |
444 | int error_waiters; /* Protected by irq_lock */ | 444 | int error_waiters; /* Protected by waiter_lock */ |
445 | atomic_t fifo_queue_waiters; | 445 | int fifo_queue_waiters; /* Protected by waiter_lock */ |
446 | uint32_t last_read_seqno; | 446 | uint32_t last_read_seqno; |
447 | spinlock_t irq_lock; | ||
448 | struct vmw_fence_manager *fman; | 447 | struct vmw_fence_manager *fman; |
449 | uint32_t irq_mask; | 448 | uint32_t irq_mask; /* Updates protected by waiter_lock */ |
450 | 449 | ||
451 | /* | 450 | /* |
452 | * Device state | 451 | * Device state |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index 0cbaf8832968..a8baf5f5e765 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | |||
@@ -252,7 +252,6 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv, | |||
252 | unsigned long timeout) | 252 | unsigned long timeout) |
253 | { | 253 | { |
254 | long ret = 1L; | 254 | long ret = 1L; |
255 | unsigned long irq_flags; | ||
256 | 255 | ||
257 | if (likely(!vmw_fifo_is_full(dev_priv, bytes))) | 256 | if (likely(!vmw_fifo_is_full(dev_priv, bytes))) |
258 | return 0; | 257 | return 0; |
@@ -262,16 +261,8 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv, | |||
262 | return vmw_fifo_wait_noirq(dev_priv, bytes, | 261 | return vmw_fifo_wait_noirq(dev_priv, bytes, |
263 | interruptible, timeout); | 262 | interruptible, timeout); |
264 | 263 | ||
265 | spin_lock(&dev_priv->waiter_lock); | 264 | vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_FIFO_PROGRESS, |
266 | if (atomic_add_return(1, &dev_priv->fifo_queue_waiters) > 0) { | 265 | &dev_priv->fifo_queue_waiters); |
267 | spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); | ||
268 | outl(SVGA_IRQFLAG_FIFO_PROGRESS, | ||
269 | dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); | ||
270 | dev_priv->irq_mask |= SVGA_IRQFLAG_FIFO_PROGRESS; | ||
271 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | ||
272 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | ||
273 | } | ||
274 | spin_unlock(&dev_priv->waiter_lock); | ||
275 | 266 | ||
276 | if (interruptible) | 267 | if (interruptible) |
277 | ret = wait_event_interruptible_timeout | 268 | ret = wait_event_interruptible_timeout |
@@ -287,14 +278,8 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv, | |||
287 | else if (likely(ret > 0)) | 278 | else if (likely(ret > 0)) |
288 | ret = 0; | 279 | ret = 0; |
289 | 280 | ||
290 | spin_lock(&dev_priv->waiter_lock); | 281 | vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_FIFO_PROGRESS, |
291 | if (atomic_dec_and_test(&dev_priv->fifo_queue_waiters)) { | 282 | &dev_priv->fifo_queue_waiters); |
292 | spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); | ||
293 | dev_priv->irq_mask &= ~SVGA_IRQFLAG_FIFO_PROGRESS; | ||
294 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | ||
295 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | ||
296 | } | ||
297 | spin_unlock(&dev_priv->waiter_lock); | ||
298 | 283 | ||
299 | return ret; | 284 | return ret; |
300 | } | 285 | } |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c index ac3eccd9223f..0c7e1723292c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c | |||
@@ -36,15 +36,13 @@ irqreturn_t vmw_irq_handler(int irq, void *arg) | |||
36 | struct vmw_private *dev_priv = vmw_priv(dev); | 36 | struct vmw_private *dev_priv = vmw_priv(dev); |
37 | uint32_t status, masked_status; | 37 | uint32_t status, masked_status; |
38 | 38 | ||
39 | spin_lock(&dev_priv->irq_lock); | ||
40 | status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); | 39 | status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); |
41 | masked_status = status & dev_priv->irq_mask; | 40 | masked_status = status & READ_ONCE(dev_priv->irq_mask); |
42 | spin_unlock(&dev_priv->irq_lock); | ||
43 | 41 | ||
44 | if (likely(status)) | 42 | if (likely(status)) |
45 | outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); | 43 | outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); |
46 | 44 | ||
47 | if (!masked_status) | 45 | if (!status) |
48 | return IRQ_NONE; | 46 | return IRQ_NONE; |
49 | 47 | ||
50 | if (masked_status & (SVGA_IRQFLAG_ANY_FENCE | | 48 | if (masked_status & (SVGA_IRQFLAG_ANY_FENCE | |
@@ -190,65 +188,51 @@ out_err: | |||
190 | return ret; | 188 | return ret; |
191 | } | 189 | } |
192 | 190 | ||
193 | void vmw_seqno_waiter_add(struct vmw_private *dev_priv) | 191 | void vmw_generic_waiter_add(struct vmw_private *dev_priv, |
192 | u32 flag, int *waiter_count) | ||
194 | { | 193 | { |
195 | spin_lock(&dev_priv->waiter_lock); | 194 | spin_lock_bh(&dev_priv->waiter_lock); |
196 | if (dev_priv->fence_queue_waiters++ == 0) { | 195 | if ((*waiter_count)++ == 0) { |
197 | unsigned long irq_flags; | 196 | outl(flag, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); |
198 | 197 | dev_priv->irq_mask |= flag; | |
199 | spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); | ||
200 | outl(SVGA_IRQFLAG_ANY_FENCE, | ||
201 | dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); | ||
202 | dev_priv->irq_mask |= SVGA_IRQFLAG_ANY_FENCE; | ||
203 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | 198 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); |
204 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | ||
205 | } | 199 | } |
206 | spin_unlock(&dev_priv->waiter_lock); | 200 | spin_unlock_bh(&dev_priv->waiter_lock); |
207 | } | 201 | } |
208 | 202 | ||
209 | void vmw_seqno_waiter_remove(struct vmw_private *dev_priv) | 203 | void vmw_generic_waiter_remove(struct vmw_private *dev_priv, |
204 | u32 flag, int *waiter_count) | ||
210 | { | 205 | { |
211 | spin_lock(&dev_priv->waiter_lock); | 206 | spin_lock_bh(&dev_priv->waiter_lock); |
212 | if (--dev_priv->fence_queue_waiters == 0) { | 207 | if (--(*waiter_count) == 0) { |
213 | unsigned long irq_flags; | 208 | dev_priv->irq_mask &= ~flag; |
214 | |||
215 | spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); | ||
216 | dev_priv->irq_mask &= ~SVGA_IRQFLAG_ANY_FENCE; | ||
217 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | 209 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); |
218 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | ||
219 | } | 210 | } |
220 | spin_unlock(&dev_priv->waiter_lock); | 211 | spin_unlock_bh(&dev_priv->waiter_lock); |
221 | } | 212 | } |
222 | 213 | ||
214 | void vmw_seqno_waiter_add(struct vmw_private *dev_priv) | ||
215 | { | ||
216 | vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_ANY_FENCE, | ||
217 | &dev_priv->fence_queue_waiters); | ||
218 | } | ||
219 | |||
220 | void vmw_seqno_waiter_remove(struct vmw_private *dev_priv) | ||
221 | { | ||
222 | vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_ANY_FENCE, | ||
223 | &dev_priv->fence_queue_waiters); | ||
224 | } | ||
223 | 225 | ||
224 | void vmw_goal_waiter_add(struct vmw_private *dev_priv) | 226 | void vmw_goal_waiter_add(struct vmw_private *dev_priv) |
225 | { | 227 | { |
226 | spin_lock(&dev_priv->waiter_lock); | 228 | vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_FENCE_GOAL, |
227 | if (dev_priv->goal_queue_waiters++ == 0) { | 229 | &dev_priv->goal_queue_waiters); |
228 | unsigned long irq_flags; | ||
229 | |||
230 | spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); | ||
231 | outl(SVGA_IRQFLAG_FENCE_GOAL, | ||
232 | dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); | ||
233 | dev_priv->irq_mask |= SVGA_IRQFLAG_FENCE_GOAL; | ||
234 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | ||
235 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | ||
236 | } | ||
237 | spin_unlock(&dev_priv->waiter_lock); | ||
238 | } | 230 | } |
239 | 231 | ||
240 | void vmw_goal_waiter_remove(struct vmw_private *dev_priv) | 232 | void vmw_goal_waiter_remove(struct vmw_private *dev_priv) |
241 | { | 233 | { |
242 | spin_lock(&dev_priv->waiter_lock); | 234 | vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_FENCE_GOAL, |
243 | if (--dev_priv->goal_queue_waiters == 0) { | 235 | &dev_priv->goal_queue_waiters); |
244 | unsigned long irq_flags; | ||
245 | |||
246 | spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); | ||
247 | dev_priv->irq_mask &= ~SVGA_IRQFLAG_FENCE_GOAL; | ||
248 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | ||
249 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | ||
250 | } | ||
251 | spin_unlock(&dev_priv->waiter_lock); | ||
252 | } | 236 | } |
253 | 237 | ||
254 | int vmw_wait_seqno(struct vmw_private *dev_priv, | 238 | int vmw_wait_seqno(struct vmw_private *dev_priv, |
@@ -305,7 +289,6 @@ void vmw_irq_preinstall(struct drm_device *dev) | |||
305 | if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK)) | 289 | if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK)) |
306 | return; | 290 | return; |
307 | 291 | ||
308 | spin_lock_init(&dev_priv->irq_lock); | ||
309 | status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); | 292 | status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); |
310 | outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); | 293 | outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); |
311 | } | 294 | } |
@@ -328,30 +311,3 @@ void vmw_irq_uninstall(struct drm_device *dev) | |||
328 | status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); | 311 | status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); |
329 | outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); | 312 | outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); |
330 | } | 313 | } |
331 | |||
332 | void vmw_generic_waiter_add(struct vmw_private *dev_priv, | ||
333 | u32 flag, int *waiter_count) | ||
334 | { | ||
335 | unsigned long irq_flags; | ||
336 | |||
337 | spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); | ||
338 | if ((*waiter_count)++ == 0) { | ||
339 | outl(flag, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); | ||
340 | dev_priv->irq_mask |= flag; | ||
341 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | ||
342 | } | ||
343 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | ||
344 | } | ||
345 | |||
346 | void vmw_generic_waiter_remove(struct vmw_private *dev_priv, | ||
347 | u32 flag, int *waiter_count) | ||
348 | { | ||
349 | unsigned long irq_flags; | ||
350 | |||
351 | spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); | ||
352 | if (--(*waiter_count) == 0) { | ||
353 | dev_priv->irq_mask &= ~flag; | ||
354 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | ||
355 | } | ||
356 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | ||
357 | } | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index a94b24d041f1..9fcd7f82995c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
@@ -78,7 +78,7 @@ int vmw_cursor_update_image(struct vmw_private *dev_priv, | |||
78 | cmd->cursor.hotspotX = hotspotX; | 78 | cmd->cursor.hotspotX = hotspotX; |
79 | cmd->cursor.hotspotY = hotspotY; | 79 | cmd->cursor.hotspotY = hotspotY; |
80 | 80 | ||
81 | vmw_fifo_commit(dev_priv, cmd_size); | 81 | vmw_fifo_commit_flush(dev_priv, cmd_size); |
82 | 82 | ||
83 | return 0; | 83 | return 0; |
84 | } | 84 | } |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index c22e2df1b336..b1fc1c02792d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | |||
@@ -717,6 +717,8 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc, | |||
717 | &event->event.tv_usec, | 717 | &event->event.tv_usec, |
718 | true); | 718 | true); |
719 | vmw_fence_obj_unreference(&fence); | 719 | vmw_fence_obj_unreference(&fence); |
720 | } else { | ||
721 | vmw_fifo_flush(dev_priv, false); | ||
720 | } | 722 | } |
721 | 723 | ||
722 | return ret; | 724 | return ret; |