struct drm_i915_private *dev_priv = info->dev->dev_private;
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe];
- if (!atomic_dec_and_test(&pipe_crc->available)) {
- atomic_inc(&pipe_crc->available);
+ spin_lock_irq(&pipe_crc->lock);
+
+ if (pipe_crc->opened) {
+ spin_unlock_irq(&pipe_crc->lock);
return -EBUSY; /* already open */
}
+ pipe_crc->opened = true;
filep->private_data = inode->i_private;
+ spin_unlock_irq(&pipe_crc->lock);
+
return 0;
}
struct drm_i915_private *dev_priv = info->dev->dev_private;
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe];
- atomic_inc(&pipe_crc->available); /* release the device */
+ spin_lock_irq(&pipe_crc->lock);
+ pipe_crc->opened = false;
+ spin_unlock_irq(&pipe_crc->lock);
return 0;
}
static int pipe_crc_data_count(struct intel_pipe_crc *pipe_crc)
{
- int head, tail;
-
- head = atomic_read(&pipe_crc->head);
- tail = atomic_read(&pipe_crc->tail);
-
- return CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR);
+ assert_spin_locked(&pipe_crc->lock);
+ return CIRC_CNT(pipe_crc->head, pipe_crc->tail,
+ INTEL_PIPE_CRC_ENTRIES_NR);
}
static ssize_t
return 0;
/* nothing to read */
+ spin_lock_irq(&pipe_crc->lock);
while (pipe_crc_data_count(pipe_crc) == 0) {
- if (filep->f_flags & O_NONBLOCK)
+ int ret;
+
+ if (filep->f_flags & O_NONBLOCK) {
+ spin_unlock_irq(&pipe_crc->lock);
return -EAGAIN;
+ }
- if (wait_event_interruptible(pipe_crc->wq,
- pipe_crc_data_count(pipe_crc)))
- return -ERESTARTSYS;
+ ret = wait_event_interruptible_lock_irq(pipe_crc->wq,
+ pipe_crc_data_count(pipe_crc), pipe_crc->lock);
+ if (ret) {
+ spin_unlock_irq(&pipe_crc->lock);
+ return ret;
+ }
}
/* We now have one or more entries to read */
- head = atomic_read(&pipe_crc->head);
- tail = atomic_read(&pipe_crc->tail);
+ head = pipe_crc->head;
+ tail = pipe_crc->tail;
n_entries = min((size_t)CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR),
count / PIPE_CRC_LINE_LEN);
+ spin_unlock_irq(&pipe_crc->lock);
+
bytes_read = 0;
n = 0;
do {
BUILD_BUG_ON_NOT_POWER_OF_2(INTEL_PIPE_CRC_ENTRIES_NR);
tail = (tail + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1);
- atomic_set(&pipe_crc->tail, tail);
n++;
} while (--n_entries);
+ spin_lock_irq(&pipe_crc->lock);
+ pipe_crc->tail = tail;
+ spin_unlock_irq(&pipe_crc->lock);
+
return bytes_read;
}
if (!pipe_crc->entries)
return -ENOMEM;
- atomic_set(&pipe_crc->head, 0);
- atomic_set(&pipe_crc->tail, 0);
+ spin_lock_irq(&pipe_crc->lock);
+ pipe_crc->head = 0;
+ pipe_crc->tail = 0;
+ spin_unlock_irq(&pipe_crc->lock);
}
pipe_crc->source = source;
/* real source -> none transition */
if (source == INTEL_PIPE_CRC_SOURCE_NONE) {
+ struct intel_pipe_crc_entry *entries;
+
DRM_DEBUG_DRIVER("stopping CRCs for pipe %c\n",
pipe_name(pipe));
intel_wait_for_vblank(dev, pipe);
- kfree(pipe_crc->entries);
+ spin_lock_irq(&pipe_crc->lock);
+ entries = pipe_crc->entries;
pipe_crc->entries = NULL;
+ spin_unlock_irq(&pipe_crc->lock);
+
+ kfree(entries);
}
return 0;
for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) {
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[i];
- atomic_set(&pipe_crc->available, 1);
+ pipe_crc->opened = false;
+ spin_lock_init(&pipe_crc->lock);
init_waitqueue_head(&pipe_crc->wq);
}
}
struct intel_pipe_crc_entry *entry;
int head, tail;
+ spin_lock(&pipe_crc->lock);
+
if (!pipe_crc->entries) {
+ spin_unlock(&pipe_crc->lock);
DRM_ERROR("spurious interrupt\n");
return;
}
- head = atomic_read(&pipe_crc->head);
- tail = atomic_read(&pipe_crc->tail);
+ head = pipe_crc->head;
+ tail = pipe_crc->tail;
if (CIRC_SPACE(head, tail, INTEL_PIPE_CRC_ENTRIES_NR) < 1) {
+ spin_unlock(&pipe_crc->lock);
DRM_ERROR("CRC buffer overflowing\n");
return;
}
entry->crc[4] = crc4;
head = (head + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1);
- atomic_set(&pipe_crc->head, head);
+ pipe_crc->head = head;
+
+ spin_unlock(&pipe_crc->lock);
wake_up_interruptible(&pipe_crc->wq);
}