i915: Re-report breadcrumbs on poll to the fence manager,
since a breadcrumb may actually turn up before a corresponding fence object has been placed on the fence ring.main
parent
a0781e7622
commit
76748efae2
|
@ -38,10 +38,10 @@
|
|||
* Initiate a sync flush if it's not already pending.
|
||||
*/
|
||||
|
||||
static void i915_initiate_rwflush(struct drm_i915_private *dev_priv,
|
||||
struct drm_fence_class_manager *fc)
|
||||
static inline void i915_initiate_rwflush(struct drm_i915_private *dev_priv,
|
||||
struct drm_fence_class_manager *fc)
|
||||
{
|
||||
if ((fc->pending_flush & DRM_I915_FENCE_TYPE_RW) &&
|
||||
if ((fc->pending_flush & DRM_I915_FENCE_TYPE_RW) &&
|
||||
!dev_priv->flush_pending) {
|
||||
dev_priv->flush_sequence = (uint32_t) READ_BREADCRUMB(dev_priv);
|
||||
dev_priv->flush_flags = fc->pending_flush;
|
||||
|
@ -52,6 +52,27 @@ static void i915_initiate_rwflush(struct drm_i915_private *dev_priv,
|
|||
}
|
||||
}
|
||||
|
||||
static inline void i915_report_rwflush(struct drm_device *dev,
|
||||
struct drm_i915_private *dev_priv)
|
||||
{
|
||||
if (unlikely(dev_priv->flush_pending)) {
|
||||
|
||||
uint32_t flush_flags;
|
||||
uint32_t i_status;
|
||||
uint32_t flush_sequence;
|
||||
|
||||
i_status = READ_HWSP(dev_priv, 0);
|
||||
if ((i_status & (1 << 12)) !=
|
||||
(dev_priv->saved_flush_status & (1 << 12))) {
|
||||
flush_flags = dev_priv->flush_flags;
|
||||
flush_sequence = dev_priv->flush_sequence;
|
||||
dev_priv->flush_pending = 0;
|
||||
drm_fence_handler(dev, 0, flush_sequence,
|
||||
flush_flags, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void i915_fence_flush(struct drm_device *dev,
|
||||
uint32_t fence_class)
|
||||
{
|
||||
|
@ -69,15 +90,13 @@ static void i915_fence_flush(struct drm_device *dev,
|
|||
write_unlock_irqrestore(&fm->lock, irq_flags);
|
||||
}
|
||||
|
||||
|
||||
static void i915_fence_poll(struct drm_device *dev, uint32_t fence_class,
|
||||
uint32_t waiting_types)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
struct drm_fence_manager *fm = &dev->fm;
|
||||
struct drm_fence_class_manager *fc = &fm->fence_class[0];
|
||||
uint32_t flush_flags = 0;
|
||||
uint32_t flush_sequence = 0;
|
||||
uint32_t i_status;
|
||||
uint32_t sequence;
|
||||
|
||||
if (unlikely(!dev_priv))
|
||||
|
@ -87,36 +106,24 @@ static void i915_fence_poll(struct drm_device *dev, uint32_t fence_class,
|
|||
* First, report any executed sync flush:
|
||||
*/
|
||||
|
||||
if (dev_priv->flush_pending) {
|
||||
i_status = READ_HWSP(dev_priv, 0);
|
||||
if ((i_status & (1 << 12)) !=
|
||||
(dev_priv->saved_flush_status & (1 << 12))) {
|
||||
flush_flags = dev_priv->flush_flags;
|
||||
flush_sequence = dev_priv->flush_sequence;
|
||||
dev_priv->flush_pending = 0;
|
||||
drm_fence_handler(dev, 0, flush_sequence, flush_flags, 0);
|
||||
}
|
||||
}
|
||||
i915_report_rwflush(dev, dev_priv);
|
||||
|
||||
/*
|
||||
* Report A new breadcrumb, and adjust IRQs.
|
||||
*/
|
||||
|
||||
if (waiting_types & DRM_FENCE_TYPE_EXE) {
|
||||
|
||||
sequence = READ_BREADCRUMB(dev_priv);
|
||||
drm_fence_handler(dev, 0, sequence,
|
||||
DRM_FENCE_TYPE_EXE, 0);
|
||||
|
||||
if (sequence != dev_priv->reported_sequence ||
|
||||
!dev_priv->reported_sequence_valid) {
|
||||
drm_fence_handler(dev, 0, sequence,
|
||||
DRM_FENCE_TYPE_EXE, 0);
|
||||
dev_priv->reported_sequence = sequence;
|
||||
dev_priv->reported_sequence_valid = 1;
|
||||
}
|
||||
|
||||
if (dev_priv->fence_irq_on && !(waiting_types & DRM_FENCE_TYPE_EXE)) {
|
||||
if (dev_priv->fence_irq_on &&
|
||||
!(fc->waiting_types & DRM_FENCE_TYPE_EXE)) {
|
||||
i915_user_irq_off(dev_priv);
|
||||
dev_priv->fence_irq_on = 0;
|
||||
} else if (!dev_priv->fence_irq_on && (waiting_types & DRM_FENCE_TYPE_EXE)) {
|
||||
} else if (!dev_priv->fence_irq_on &&
|
||||
(fc->waiting_types & DRM_FENCE_TYPE_EXE)) {
|
||||
i915_user_irq_on(dev_priv);
|
||||
dev_priv->fence_irq_on = 1;
|
||||
}
|
||||
|
@ -129,19 +136,11 @@ static void i915_fence_poll(struct drm_device *dev, uint32_t fence_class,
|
|||
i915_initiate_rwflush(dev_priv, fc);
|
||||
|
||||
/*
|
||||
* And possibly, but unlikely, they finish immediately.
|
||||
* And possibly, but unlikely, they finish immediately.
|
||||
*/
|
||||
|
||||
if (dev_priv->flush_pending) {
|
||||
i_status = READ_HWSP(dev_priv, 0);
|
||||
if (unlikely((i_status & (1 << 12)) !=
|
||||
(dev_priv->saved_flush_status & (1 << 12)))) {
|
||||
flush_flags = dev_priv->flush_flags;
|
||||
flush_sequence = dev_priv->flush_sequence;
|
||||
dev_priv->flush_pending = 0;
|
||||
drm_fence_handler(dev, 0, flush_sequence, flush_flags, 0);
|
||||
}
|
||||
}
|
||||
i915_report_rwflush(dev, dev_priv);
|
||||
|
||||
}
|
||||
|
||||
static int i915_fence_emit_sequence(struct drm_device *dev, uint32_t class,
|
||||
|
@ -258,27 +257,6 @@ static uint32_t i915_fence_needed_flush(struct drm_fence_object *fence)
|
|||
return flush_flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* In the very unlikely event that "poll" is not really called very often
|
||||
* we need the following function to handle sequence wraparounds.
|
||||
*/
|
||||
|
||||
void i915_invalidate_reported_sequence(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = (struct drm_i915_private *)
|
||||
dev->dev_private;
|
||||
struct drm_fence_manager *fm = &dev->fm;
|
||||
unsigned long irq_flags;
|
||||
|
||||
if (unlikely(!dev_priv))
|
||||
return;
|
||||
|
||||
write_lock_irqsave(&fm->lock, irq_flags);
|
||||
dev_priv->reported_sequence_valid = 0;
|
||||
write_unlock_irqrestore(&fm->lock, irq_flags);
|
||||
}
|
||||
|
||||
|
||||
struct drm_fence_driver i915_fence_driver = {
|
||||
.num_classes = 1,
|
||||
.wrap_diff = (1U << (BREADCRUMB_BITS - 1)),
|
||||
|
|
|
@ -422,9 +422,6 @@ void i915_emit_breadcrumb(struct drm_device *dev)
|
|||
RING_LOCALS;
|
||||
|
||||
if (++dev_priv->counter > BREADCRUMB_MASK) {
|
||||
#ifdef I915_HAVE_FENCE
|
||||
i915_invalidate_reported_sequence(dev);
|
||||
#endif
|
||||
dev_priv->counter = 1;
|
||||
DRM_DEBUG("Breadcrumb counter wrapped around\n");
|
||||
}
|
||||
|
|
|
@ -136,8 +136,6 @@ typedef struct drm_i915_private {
|
|||
uint32_t flush_flags;
|
||||
uint32_t flush_pending;
|
||||
uint32_t saved_flush_status;
|
||||
uint32_t reported_sequence;
|
||||
int reported_sequence_valid;
|
||||
#endif
|
||||
#ifdef I915_HAVE_BUFFER
|
||||
void *agp_iomap;
|
||||
|
|
Loading…
Reference in New Issue