/* * Read a single request into the userspace filesystem's buffer. This * function waits until a request is available, then removes it from * the pending list and copies request data to userspace buffer. If * no reply is needed (FORGET) or request has been aborted or there * was an error during the copying then it's finished by calling * request_end(). Otherwise add it to the processing list, and set * the 'sent' flag. */ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov, unsigned long nr_segs, loff_t *off) { int err; struct fuse_req *req; struct fuse_in *in; struct fuse_copy_state cs; unsigned reqsize; struct fuse_conn *fc = fuse_get_conn(file); if (!fc) return -EPERM; restart: spin_lock(&fc->lock); err = -EAGAIN; if ((file->f_flags & O_NONBLOCK) && fc->connected && !request_pending(fc)) goto err_unlock; request_wait(fc); err = -ENODEV; if (!fc->connected) goto err_unlock; err = -ERESTARTSYS; if (!request_pending(fc)) goto err_unlock; if (!list_empty(&fc->interrupts)) { req = list_entry(fc->interrupts.next, struct fuse_req, intr_entry); return fuse_read_interrupt(fc, req, iov, nr_segs); }
static int mdp4_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, uint32_t handle, uint32_t width, uint32_t height) { struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); struct mdp4_kms *mdp4_kms = get_kms(crtc); struct drm_device *dev = crtc->dev; struct drm_gem_object *cursor_bo, *old_bo; unsigned long flags; uint32_t iova; int ret; if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) { dev_err(dev->dev, "bad cursor size: %dx%d\n", width, height); return -EINVAL; } if (handle) { cursor_bo = drm_gem_object_lookup(dev, file_priv, handle); if (!cursor_bo) return -ENOENT; } else { cursor_bo = NULL; } if (cursor_bo) { ret = msm_gem_get_iova(cursor_bo, mdp4_kms->id, &iova); if (ret) goto fail; } else { iova = 0; } spin_lock_irqsave(&mdp4_crtc->cursor.lock, flags); old_bo = mdp4_crtc->cursor.next_bo; mdp4_crtc->cursor.next_bo = cursor_bo; mdp4_crtc->cursor.next_iova = iova; mdp4_crtc->cursor.width = width; mdp4_crtc->cursor.height = height; mdp4_crtc->cursor.stale = true; spin_unlock_irqrestore(&mdp4_crtc->cursor.lock, flags); if (old_bo) { /* drop our previous reference: */ msm_gem_put_iova(old_bo, mdp4_kms->id); drm_gem_object_unreference_unlocked(old_bo); } request_pending(crtc, PENDING_CURSOR); return 0; fail: drm_gem_object_unreference_unlocked(cursor_bo); return ret; }
static int mdp4_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) { struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); unsigned long flags; spin_lock_irqsave(&mdp4_crtc->cursor.lock, flags); mdp4_crtc->cursor.x = x; mdp4_crtc->cursor.y = y; spin_unlock_irqrestore(&mdp4_crtc->cursor.lock, flags); crtc_flush(crtc); request_pending(crtc, PENDING_CURSOR); return 0; }
static void pageflip_cb(struct msm_fence_cb *cb) { struct mdp4_crtc *mdp4_crtc = container_of(cb, struct mdp4_crtc, pageflip_cb); struct drm_crtc *crtc = &mdp4_crtc->base; struct drm_framebuffer *fb = crtc->fb; if (!fb) return; mdp4_plane_set_scanout(mdp4_crtc->plane, fb); crtc_flush(crtc); /* enable vblank to complete flip: */ request_pending(crtc, PENDING_FLIP); }
/* Wait until a request is available on the pending list */ static void request_wait(struct fuse_conn *fc) { DECLARE_WAITQUEUE(wait, current); add_wait_queue_exclusive(&fc->waitq, &wait); while (fc->connected && !request_pending(fc)) { set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) break; spin_unlock(&fc->lock); schedule(); spin_lock(&fc->lock); } set_current_state(TASK_RUNNING); remove_wait_queue(&fc->waitq, &wait); }
/* unlike update_fb(), take a ref to the new scanout fb *before* updating * plane, then call this. Needed to ensure we don't unref the buffer that * is actually still being scanned out. * * Note that this whole thing goes away with atomic.. since we can defer * calling into driver until rendering is done. */ static void update_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb) { struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); /* flush updates, to make sure hw is updated to new scanout fb, * so that we can safely queue unref to current fb (ie. next * vblank we know hw is done w/ previous scanout_fb). */ crtc_flush(crtc); if (mdp4_crtc->scanout_fb) drm_flip_work_queue(&mdp4_crtc->unref_fb_work, mdp4_crtc->scanout_fb); mdp4_crtc->scanout_fb = fb; /* enable vblank to complete flip: */ request_pending(crtc, PENDING_FLIP); }