/* Called under the mutex to grab exclusive access to a drive */ static int grab_drive(struct floppy_state *fs, enum swim_state state, int interruptible) { unsigned long flags; swim3_dbg("%s", "-> grab drive\n"); spin_lock_irqsave(&swim3_lock, flags); if (fs->state != idle && fs->state != available) { ++fs->wanted; /* this will enable irqs in order to sleep */ if (!interruptible) wait_event_lock_irq(fs->wait, fs->state == available, swim3_lock); else if (wait_event_interruptible_lock_irq(fs->wait, fs->state == available, swim3_lock)) { --fs->wanted; spin_unlock_irqrestore(&swim3_lock, flags); return -EINTR; } --fs->wanted; } fs->state = state; spin_unlock_irqrestore(&swim3_lock, flags); return 0; }
static ssize_t crtc_crc_read(struct file *filep, char __user *user_buf, size_t count, loff_t *pos) { struct drm_crtc *crtc = filep->f_inode->i_private; struct drm_crtc_crc *crc = &crtc->crc; struct drm_crtc_crc_entry *entry; char buf[MAX_LINE_LEN]; int ret, i; spin_lock_irq(&crc->lock); if (!crc->source) { spin_unlock_irq(&crc->lock); return 0; } /* Nothing to read? */ while (crtc_crc_data_count(crc) == 0) { if (filep->f_flags & O_NONBLOCK) { spin_unlock_irq(&crc->lock); return -EAGAIN; } ret = wait_event_interruptible_lock_irq(crc->wq, crtc_crc_data_count(crc), crc->lock); if (ret) { spin_unlock_irq(&crc->lock); return ret; } } /* We know we have an entry to be read */ entry = &crc->entries[crc->tail]; if (count < LINE_LEN(crc->values_cnt)) { spin_unlock_irq(&crc->lock); return -EINVAL; } BUILD_BUG_ON_NOT_POWER_OF_2(DRM_CRC_ENTRIES_NR); crc->tail = (crc->tail + 1) & (DRM_CRC_ENTRIES_NR - 1); spin_unlock_irq(&crc->lock); if (entry->has_frame_counter) sprintf(buf, "0x%08x", entry->frame); else sprintf(buf, "XXXXXXXXXX"); for (i = 0; i < crc->values_cnt; i++) sprintf(buf + 10 + i * 11, " 0x%08x", entry->crcs[i]); sprintf(buf + 10 + crc->values_cnt * 11, "\n"); if (copy_to_user(user_buf, buf, LINE_LEN(crc->values_cnt))) return -EFAULT; return LINE_LEN(crc->values_cnt); }
static ssize_t i915_pipe_crc_read(struct file *filep, char __user *user_buf, size_t count, loff_t *pos) { struct pipe_crc_info *info = filep->private_data; struct drm_i915_private *dev_priv = info->dev_priv; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; char buf[PIPE_CRC_BUFFER_LEN]; int n_entries; ssize_t bytes_read; /* * Don't allow user space to provide buffers not big enough to hold * a line of data. */ if (count < PIPE_CRC_LINE_LEN) return -EINVAL; if (pipe_crc->source == INTEL_PIPE_CRC_SOURCE_NONE) return 0; /* nothing to read */ spin_lock_irq(&pipe_crc->lock); while (pipe_crc_data_count(pipe_crc) == 0) { int ret; if (filep->f_flags & O_NONBLOCK) { spin_unlock_irq(&pipe_crc->lock); return -EAGAIN; } 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 */ n_entries = count / PIPE_CRC_LINE_LEN; bytes_read = 0; while (n_entries > 0) { struct intel_pipe_crc_entry *entry = &pipe_crc->entries[pipe_crc->tail]; if (CIRC_CNT(pipe_crc->head, pipe_crc->tail, INTEL_PIPE_CRC_ENTRIES_NR) < 1) break; BUILD_BUG_ON_NOT_POWER_OF_2(INTEL_PIPE_CRC_ENTRIES_NR); pipe_crc->tail = (pipe_crc->tail + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); bytes_read += snprintf(buf, PIPE_CRC_BUFFER_LEN, "%8u %8x %8x %8x %8x %8x\n", entry->frame, entry->crc[0], entry->crc[1], entry->crc[2], entry->crc[3], entry->crc[4]); spin_unlock_irq(&pipe_crc->lock); if (copy_to_user(user_buf, buf, PIPE_CRC_LINE_LEN)) return -EFAULT; user_buf += PIPE_CRC_LINE_LEN; n_entries--; spin_lock_irq(&pipe_crc->lock); } spin_unlock_irq(&pipe_crc->lock); return bytes_read; }
static int crtc_crc_open(struct inode *inode, struct file *filep) { struct drm_crtc *crtc = inode->i_private; struct drm_crtc_crc *crc = &crtc->crc; struct drm_crtc_crc_entry *entries = NULL; size_t values_cnt; int ret = 0; if (drm_drv_uses_atomic_modeset(crtc->dev)) { ret = drm_modeset_lock_single_interruptible(&crtc->mutex); if (ret) return ret; if (!crtc->state->active) ret = -EIO; drm_modeset_unlock(&crtc->mutex); if (ret) return ret; } spin_lock_irq(&crc->lock); if (!crc->opened) crc->opened = true; else ret = -EBUSY; spin_unlock_irq(&crc->lock); if (ret) return ret; ret = crtc->funcs->set_crc_source(crtc, crc->source, &values_cnt); if (ret) goto err; if (WARN_ON(values_cnt > DRM_MAX_CRC_NR)) { ret = -EINVAL; goto err_disable; } if (WARN_ON(values_cnt == 0)) { ret = -EINVAL; goto err_disable; } entries = kcalloc(DRM_CRC_ENTRIES_NR, sizeof(*entries), GFP_KERNEL); if (!entries) { ret = -ENOMEM; goto err_disable; } spin_lock_irq(&crc->lock); crc->entries = entries; crc->values_cnt = values_cnt; /* * Only return once we got a first frame, so userspace doesn't have to * guess when this particular piece of HW will be ready to start * generating CRCs. */ ret = wait_event_interruptible_lock_irq(crc->wq, crtc_crc_data_count(crc), crc->lock); spin_unlock_irq(&crc->lock); if (ret) goto err_disable; return 0; err_disable: crtc->funcs->set_crc_source(crtc, NULL, &values_cnt); err: spin_lock_irq(&crc->lock); crtc_crc_cleanup(crc); spin_unlock_irq(&crc->lock); return ret; }