Skip to content

Commit c82f55f

Browse files
en4bzzackr
authored andcommitted
drm/vmwgfx: Update last_read_seqno under the fence lock
There was a possible race in vmw_update_seqno. Because of this race it was possible for last_read_seqno to go backwards. Remove this function and replace it with vmw_update_fences which now sets and returns the last_read_seqno while holding the fence lock. This serialization via the fence lock ensures that last_read_seqno is monotonic again. Signed-off-by: Ian Forbes <[email protected]> Signed-off-by: Zack Rusin <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent a72002c commit c82f55f

File tree

7 files changed

+22
-31
lines changed

7 files changed

+22
-31
lines changed

drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ int vmw_cmd_send_fence(struct vmw_private *dev_priv, uint32_t *seqno)
544544
cmd_fence = (struct svga_fifo_cmd_fence *) fm;
545545
cmd_fence->fence = *seqno;
546546
vmw_cmd_commit_flush(dev_priv, bytes);
547-
vmw_update_seqno(dev_priv);
547+
vmw_fences_update(dev_priv->fman);
548548

549549
out_err:
550550
return ret;

drivers/gpu/drm/vmwgfx/vmwgfx_drv.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -440,8 +440,10 @@ static int vmw_device_init(struct vmw_private *dev_priv)
440440
vmw_write(dev_priv, SVGA_REG_CONFIG_DONE, 1);
441441
}
442442

443-
dev_priv->last_read_seqno = vmw_fence_read(dev_priv);
444-
atomic_set(&dev_priv->marker_seq, dev_priv->last_read_seqno);
443+
u32 seqno = vmw_fence_read(dev_priv);
444+
445+
atomic_set(&dev_priv->last_read_seqno, seqno);
446+
atomic_set(&dev_priv->marker_seq, seqno);
445447
return 0;
446448
}
447449

@@ -454,7 +456,7 @@ static void vmw_device_fini(struct vmw_private *vmw)
454456
while (vmw_read(vmw, SVGA_REG_BUSY) != 0)
455457
;
456458

457-
vmw->last_read_seqno = vmw_fence_read(vmw);
459+
atomic_set(&vmw->last_read_seqno, vmw_fence_read(vmw));
458460

459461
vmw_write(vmw, SVGA_REG_CONFIG_DONE,
460462
vmw->config_done_state);

drivers/gpu/drm/vmwgfx/vmwgfx_drv.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ struct vmw_private {
522522
int cmdbuf_waiters; /* Protected by waiter_lock */
523523
int error_waiters; /* Protected by waiter_lock */
524524
int fifo_queue_waiters; /* Protected by waiter_lock */
525-
uint32_t last_read_seqno;
525+
atomic_t last_read_seqno;
526526
struct vmw_fence_manager *fman;
527527
uint32_t irq_mask; /* Updates protected by waiter_lock */
528528

@@ -1006,7 +1006,6 @@ extern int vmw_fallback_wait(struct vmw_private *dev_priv,
10061006
uint32_t seqno,
10071007
bool interruptible,
10081008
unsigned long timeout);
1009-
extern void vmw_update_seqno(struct vmw_private *dev_priv);
10101009
extern void vmw_seqno_waiter_add(struct vmw_private *dev_priv);
10111010
extern void vmw_seqno_waiter_remove(struct vmw_private *dev_priv);
10121011
extern void vmw_goal_waiter_add(struct vmw_private *dev_priv);

drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3878,8 +3878,7 @@ vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
38783878

38793879
fence_rep.handle = fence_handle;
38803880
fence_rep.seqno = fence->base.seqno;
3881-
vmw_update_seqno(dev_priv);
3882-
fence_rep.passed_seqno = dev_priv->last_read_seqno;
3881+
fence_rep.passed_seqno = vmw_fences_update(dev_priv->fman);
38833882
}
38843883

38853884
/*

drivers/gpu/drm/vmwgfx/vmwgfx_fence.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ vmwgfx_wait_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
172172
wake_up_process(wait->task);
173173
}
174174

175-
static void __vmw_fences_update(struct vmw_fence_manager *fman);
175+
static u32 __vmw_fences_update(struct vmw_fence_manager *fman);
176176

177177
static long vmw_fence_wait(struct dma_fence *f, bool intr, signed long timeout)
178178
{
@@ -457,7 +457,7 @@ static bool vmw_fence_goal_check_locked(struct vmw_fence_obj *fence)
457457
return true;
458458
}
459459

460-
static void __vmw_fences_update(struct vmw_fence_manager *fman)
460+
static u32 __vmw_fences_update(struct vmw_fence_manager *fman)
461461
{
462462
struct vmw_fence_obj *fence, *next_fence;
463463
struct list_head action_list;
@@ -495,13 +495,17 @@ static void __vmw_fences_update(struct vmw_fence_manager *fman)
495495

496496
if (!list_empty(&fman->cleanup_list))
497497
(void) schedule_work(&fman->work);
498+
atomic_set_release(&fman->dev_priv->last_read_seqno, seqno);
499+
return seqno;
498500
}
499501

500-
void vmw_fences_update(struct vmw_fence_manager *fman)
502+
u32 vmw_fences_update(struct vmw_fence_manager *fman)
501503
{
504+
u32 seqno;
502505
spin_lock(&fman->lock);
503-
__vmw_fences_update(fman);
506+
seqno = __vmw_fences_update(fman);
504507
spin_unlock(&fman->lock);
508+
return seqno;
505509
}
506510

507511
bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence)
@@ -778,7 +782,6 @@ int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data,
778782
(struct drm_vmw_fence_signaled_arg *) data;
779783
struct ttm_base_object *base;
780784
struct vmw_fence_obj *fence;
781-
struct vmw_fence_manager *fman;
782785
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
783786
struct vmw_private *dev_priv = vmw_priv(dev);
784787

@@ -787,14 +790,11 @@ int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data,
787790
return PTR_ERR(base);
788791

789792
fence = &(container_of(base, struct vmw_user_fence, base)->fence);
790-
fman = fman_from_fence(fence);
791793

792794
arg->signaled = vmw_fence_obj_signaled(fence);
793795

794796
arg->signaled_flags = arg->flags;
795-
spin_lock(&fman->lock);
796-
arg->passed_seqno = dev_priv->last_read_seqno;
797-
spin_unlock(&fman->lock);
797+
arg->passed_seqno = atomic_read_acquire(&dev_priv->last_read_seqno);
798798

799799
ttm_base_object_unref(&base);
800800

drivers/gpu/drm/vmwgfx/vmwgfx_fence.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ vmw_fence_obj_reference(struct vmw_fence_obj *fence)
8686
return fence;
8787
}
8888

89-
extern void vmw_fences_update(struct vmw_fence_manager *fman);
89+
u32 vmw_fences_update(struct vmw_fence_manager *fman);
9090

9191
extern bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence);
9292

drivers/gpu/drm/vmwgfx/vmwgfx_irq.c

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -123,26 +123,17 @@ static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t seqno)
123123
return (vmw_read(dev_priv, SVGA_REG_BUSY) == 0);
124124
}
125125

126-
void vmw_update_seqno(struct vmw_private *dev_priv)
127-
{
128-
uint32_t seqno = vmw_fence_read(dev_priv);
129-
130-
if (dev_priv->last_read_seqno != seqno) {
131-
dev_priv->last_read_seqno = seqno;
132-
vmw_fences_update(dev_priv->fman);
133-
}
134-
}
135-
136126
bool vmw_seqno_passed(struct vmw_private *dev_priv,
137127
uint32_t seqno)
138128
{
139129
bool ret;
130+
u32 last_read_seqno = atomic_read_acquire(&dev_priv->last_read_seqno);
140131

141-
if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
132+
if (last_read_seqno - seqno < VMW_FENCE_WRAP)
142133
return true;
143134

144-
vmw_update_seqno(dev_priv);
145-
if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
135+
last_read_seqno = vmw_fences_update(dev_priv->fman);
136+
if (last_read_seqno - seqno < VMW_FENCE_WRAP)
146137
return true;
147138

148139
if (!vmw_has_fences(dev_priv) && vmw_fifo_idle(dev_priv, seqno))

0 commit comments

Comments
 (0)