aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@gmail.com>2015-11-07 02:16:29 -0500
committerDave Airlie <airlied@gmail.com>2015-11-07 02:16:29 -0500
commitd0baf9218cacd9dd606c75f9961f94172b16de12 (patch)
treebf52d15748429f88177d44fd404d76523c784952
parente02328f47bd75fde9decf9657ec7d769b370f857 (diff)
parentd2e8851a909c76c6f0b34553f2c9993808bc1d58 (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.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h9
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c23
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_irq.c104
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c2
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
193void vmw_seqno_waiter_add(struct vmw_private *dev_priv) 191void 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
209void vmw_seqno_waiter_remove(struct vmw_private *dev_priv) 203void 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
214void 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
220void 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
224void vmw_goal_waiter_add(struct vmw_private *dev_priv) 226void 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
240void vmw_goal_waiter_remove(struct vmw_private *dev_priv) 232void 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
254int vmw_wait_seqno(struct vmw_private *dev_priv, 238int 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
332void 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
346void 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;