Skip to content

Commit 1d6595b

Browse files
committed
drm/vmwgfx: Fix fencing on SVGAv3
Port of the vmwgfx to SVGAv3 lacked support for fencing. SVGAv3 removed FIFO's and replaced them with command buffers and extra registers. The initial version of SVGAv3 lacked support for most advanced features (e.g. 3D) which made fences unnecessary. That is no longer the case, especially as 3D support is being turned on. Switch from FIFO commands and capabilities to command buffers and extra registers to enable fences on SVGAv3. Fixes: 2cd80db ("drm/vmwgfx: Add basic support for SVGA3") Signed-off-by: Zack Rusin <zackr@vmware.com> Reviewed-by: Martin Krastev <krastevm@vmware.com> Reviewed-by: Maaz Mombasawala <mombasawalam@vmware.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220302152426.885214-5-zack@kde.org
1 parent 5005e98 commit 1d6595b

5 files changed

Lines changed: 53 additions & 19 deletions

File tree

drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ int vmw_cmd_send_fence(struct vmw_private *dev_priv, uint32_t *seqno)
528528
*seqno = atomic_add_return(1, &dev_priv->marker_seq);
529529
} while (*seqno == 0);
530530

531-
if (!(vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_FENCE)) {
531+
if (!vmw_has_fences(dev_priv)) {
532532

533533
/*
534534
* Don't request hardware to send a fence. The

drivers/gpu/drm/vmwgfx/vmwgfx_drv.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1679,4 +1679,12 @@ static inline void vmw_irq_status_write(struct vmw_private *vmw,
16791679
outl(status, vmw->io_start + SVGA_IRQSTATUS_PORT);
16801680
}
16811681

1682+
static inline bool vmw_has_fences(struct vmw_private *vmw)
1683+
{
1684+
if ((vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS |
1685+
SVGA_CAP_CMD_BUFFERS_2)) != 0)
1686+
return true;
1687+
return (vmw_fifo_caps(vmw) & SVGA_FIFO_CAP_FENCE) != 0;
1688+
}
1689+
16821690
#endif

drivers/gpu/drm/vmwgfx/vmwgfx_fence.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,22 @@ fman_from_fence(struct vmw_fence_obj *fence)
8282
return container_of(fence->base.lock, struct vmw_fence_manager, lock);
8383
}
8484

85+
static u32 vmw_fence_goal_read(struct vmw_private *vmw)
86+
{
87+
if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0)
88+
return vmw_read(vmw, SVGA_REG_FENCE_GOAL);
89+
else
90+
return vmw_fifo_mem_read(vmw, SVGA_FIFO_FENCE_GOAL);
91+
}
92+
93+
static void vmw_fence_goal_write(struct vmw_private *vmw, u32 value)
94+
{
95+
if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0)
96+
vmw_write(vmw, SVGA_REG_FENCE_GOAL, value);
97+
else
98+
vmw_fifo_mem_write(vmw, SVGA_FIFO_FENCE_GOAL, value);
99+
}
100+
85101
/*
86102
* Note on fencing subsystem usage of irqs:
87103
* Typically the vmw_fences_update function is called
@@ -392,17 +408,16 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman,
392408
if (likely(!fman->seqno_valid))
393409
return false;
394410

395-
goal_seqno = vmw_fifo_mem_read(fman->dev_priv, SVGA_FIFO_FENCE_GOAL);
411+
goal_seqno = vmw_fence_goal_read(fman->dev_priv);
396412
if (likely(passed_seqno - goal_seqno >= VMW_FENCE_WRAP))
397413
return false;
398414

399415
fman->seqno_valid = false;
400416
list_for_each_entry(fence, &fman->fence_list, head) {
401417
if (!list_empty(&fence->seq_passed_actions)) {
402418
fman->seqno_valid = true;
403-
vmw_fifo_mem_write(fman->dev_priv,
404-
SVGA_FIFO_FENCE_GOAL,
405-
fence->base.seqno);
419+
vmw_fence_goal_write(fman->dev_priv,
420+
fence->base.seqno);
406421
break;
407422
}
408423
}
@@ -434,13 +449,12 @@ static bool vmw_fence_goal_check_locked(struct vmw_fence_obj *fence)
434449
if (dma_fence_is_signaled_locked(&fence->base))
435450
return false;
436451

437-
goal_seqno = vmw_fifo_mem_read(fman->dev_priv, SVGA_FIFO_FENCE_GOAL);
452+
goal_seqno = vmw_fence_goal_read(fman->dev_priv);
438453
if (likely(fman->seqno_valid &&
439454
goal_seqno - fence->base.seqno < VMW_FENCE_WRAP))
440455
return false;
441456

442-
vmw_fifo_mem_write(fman->dev_priv, SVGA_FIFO_FENCE_GOAL,
443-
fence->base.seqno);
457+
vmw_fence_goal_write(fman->dev_priv, fence->base.seqno);
444458
fman->seqno_valid = true;
445459

446460
return true;

drivers/gpu/drm/vmwgfx/vmwgfx_irq.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@
3232

3333
#define VMW_FENCE_WRAP (1 << 24)
3434

35+
static u32 vmw_irqflag_fence_goal(struct vmw_private *vmw)
36+
{
37+
if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0)
38+
return SVGA_IRQFLAG_REG_FENCE_GOAL;
39+
else
40+
return SVGA_IRQFLAG_FENCE_GOAL;
41+
}
42+
3543
/**
3644
* vmw_thread_fn - Deferred (process context) irq handler
3745
*
@@ -96,7 +104,7 @@ static irqreturn_t vmw_irq_handler(int irq, void *arg)
96104
wake_up_all(&dev_priv->fifo_queue);
97105

98106
if ((masked_status & (SVGA_IRQFLAG_ANY_FENCE |
99-
SVGA_IRQFLAG_FENCE_GOAL)) &&
107+
vmw_irqflag_fence_goal(dev_priv))) &&
100108
!test_and_set_bit(VMW_IRQTHREAD_FENCE, dev_priv->irqthread_pending))
101109
ret = IRQ_WAKE_THREAD;
102110

@@ -137,8 +145,7 @@ bool vmw_seqno_passed(struct vmw_private *dev_priv,
137145
if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
138146
return true;
139147

140-
if (!(vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_FENCE) &&
141-
vmw_fifo_idle(dev_priv, seqno))
148+
if (!vmw_has_fences(dev_priv) && vmw_fifo_idle(dev_priv, seqno))
142149
return true;
143150

144151
/**
@@ -160,6 +167,7 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
160167
unsigned long timeout)
161168
{
162169
struct vmw_fifo_state *fifo_state = dev_priv->fifo;
170+
bool fifo_down = false;
163171

164172
uint32_t count = 0;
165173
uint32_t signal_seq;
@@ -176,12 +184,14 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
176184
*/
177185

178186
if (fifo_idle) {
179-
down_read(&fifo_state->rwsem);
180187
if (dev_priv->cman) {
181188
ret = vmw_cmdbuf_idle(dev_priv->cman, interruptible,
182189
10*HZ);
183190
if (ret)
184191
goto out_err;
192+
} else if (fifo_state) {
193+
down_read(&fifo_state->rwsem);
194+
fifo_down = true;
185195
}
186196
}
187197

@@ -218,12 +228,12 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
218228
}
219229
}
220230
finish_wait(&dev_priv->fence_queue, &__wait);
221-
if (ret == 0 && fifo_idle)
231+
if (ret == 0 && fifo_idle && fifo_state)
222232
vmw_fence_write(dev_priv, signal_seq);
223233

224234
wake_up_all(&dev_priv->fence_queue);
225235
out_err:
226-
if (fifo_idle)
236+
if (fifo_down)
227237
up_read(&fifo_state->rwsem);
228238

229239
return ret;
@@ -266,13 +276,13 @@ void vmw_seqno_waiter_remove(struct vmw_private *dev_priv)
266276

267277
void vmw_goal_waiter_add(struct vmw_private *dev_priv)
268278
{
269-
vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_FENCE_GOAL,
279+
vmw_generic_waiter_add(dev_priv, vmw_irqflag_fence_goal(dev_priv),
270280
&dev_priv->goal_queue_waiters);
271281
}
272282

273283
void vmw_goal_waiter_remove(struct vmw_private *dev_priv)
274284
{
275-
vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_FENCE_GOAL,
285+
vmw_generic_waiter_remove(dev_priv, vmw_irqflag_fence_goal(dev_priv),
276286
&dev_priv->goal_queue_waiters);
277287
}
278288

drivers/gpu/drm/vmwgfx/vmwgfx_kms.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,7 +1344,6 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
13441344
ret = vmw_kms_new_framebuffer_surface(dev_priv, surface, &vfb,
13451345
mode_cmd,
13461346
is_bo_proxy);
1347-
13481347
/*
13491348
* vmw_create_bo_proxy() adds a reference that is no longer
13501349
* needed
@@ -1385,13 +1384,16 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
13851384
ret = vmw_user_lookup_handle(dev_priv, file_priv,
13861385
mode_cmd->handles[0],
13871386
&surface, &bo);
1388-
if (ret)
1387+
if (ret) {
1388+
DRM_ERROR("Invalid buffer object handle %u (0x%x).\n",
1389+
mode_cmd->handles[0], mode_cmd->handles[0]);
13891390
goto err_out;
1391+
}
13901392

13911393

13921394
if (!bo &&
13931395
!vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height)) {
1394-
DRM_ERROR("Surface size cannot exceed %dx%d",
1396+
DRM_ERROR("Surface size cannot exceed %dx%d\n",
13951397
dev_priv->texture_max_width,
13961398
dev_priv->texture_max_height);
13971399
goto err_out;

0 commit comments

Comments
 (0)