From patchwork Tue Sep 29 18:09:53 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Russell King X-Patchwork-Id: 7289341 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 2DA079F302 for ; Tue, 29 Sep 2015 18:17:32 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 42185206C0 for ; Tue, 29 Sep 2015 18:17:31 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 808DA20687 for ; Tue, 29 Sep 2015 18:17:25 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id CF3876E335; Tue, 29 Sep 2015 11:17:24 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from pandora.arm.linux.org.uk (pandora.arm.linux.org.uk [78.32.30.218]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5B4C96E466 for ; Tue, 29 Sep 2015 11:17:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=arm.linux.org.uk; s=pandora-2014; h=Date:Sender:Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Subject:To:From:References:In-Reply-To; bh=xZlUSMKmndM03jtxoy46Z1ztiBZfQvUdIrM6IXcLnkA=; b=NG1kF8Y/p5SGiW1OpJLmKNit2ZN3jpZAAOSCjkKzJvYf7Wh5G2qEvKqV3bCTJZhrezNOlO1oFDxv6J4RGErNPww25QzhCdRQnVOCNEYevSIEuFZEUodOFv0O2GPSIg4EfLi6IA4y0CaEYL4CxPwu+HluhyVhU2YnfOXS0MEZnzw=; Received: from e0022681537dd.dyn.arm.linux.org.uk ([2002:4e20:1eda:1:222:68ff:fe15:37dd]:44966 helo=rmk-PC.arm.linux.org.uk) by pandora.arm.linux.org.uk with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.82_1-5b7a7c0-XX) (envelope-from ) id 1ZgzLe-0004JY-9O for dri-devel@lists.freedesktop.org; Tue, 29 Sep 2015 19:09:54 +0100 Received: from rmk by rmk-PC.arm.linux.org.uk with local (Exim 4.82_1-5b7a7c0-XX) (envelope-from ) id 1ZgzLd-0003kn-AG for dri-devel@lists.freedesktop.org; Tue, 29 Sep 2015 19:09:53 +0100 In-Reply-To: <20150929180843.GP21513@n2100.arm.linux.org.uk> References: <20150929180843.GP21513@n2100.arm.linux.org.uk> From: Russell King To: dri-devel@lists.freedesktop.org Subject: [PATCH 05/20] drm/armada: redo locking and atomics for armada_drm_crtc_complete_frame_work() MIME-Version: 1.0 Content-Disposition: inline Message-Id: Date: Tue, 29 Sep 2015 19:09:53 +0100 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP We can do better with armada_drm_crtc_complete_frame_work() - we can avoid taking the event lock unless a call to drm_send_vblank_event() is required, and using cmpxchg() and xchg(), we can eliminate the locking around dcrtc->frame_work entirely. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 53 ++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 8c43ecc19c15..5d627646601e 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -215,7 +215,6 @@ static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc, struct armada_frame_work *work) { struct drm_device *dev = dcrtc->crtc.dev; - unsigned long flags; int ret; ret = drm_vblank_get(dev, dcrtc->num); @@ -224,30 +223,29 @@ static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc, return ret; } - spin_lock_irqsave(&dev->event_lock, flags); - if (!dcrtc->frame_work) - dcrtc->frame_work = work; - else - ret = -EBUSY; - spin_unlock_irqrestore(&dev->event_lock, flags); - - if (ret) + if (cmpxchg(&dcrtc->frame_work, NULL, work)) { drm_vblank_put(dev, dcrtc->num); + ret = -EBUSY; + } return ret; } -static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc) +static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc, + struct armada_frame_work *work) { struct drm_device *dev = dcrtc->crtc.dev; - struct armada_frame_work *work = dcrtc->frame_work; - - dcrtc->frame_work = NULL; + unsigned long flags; + spin_lock_irqsave(&dcrtc->irq_lock, flags); armada_drm_crtc_update_regs(dcrtc, work->regs); + spin_unlock_irqrestore(&dcrtc->irq_lock, flags); - if (work->event) + if (work->event) { + spin_lock_irqsave(&dev->event_lock, flags); drm_send_vblank_event(dev, dcrtc->num, work->event); + spin_unlock_irqrestore(&dev->event_lock, flags); + } drm_vblank_put(dev, dcrtc->num); @@ -293,7 +291,7 @@ static void armada_drm_crtc_finish_fb(struct armada_crtc *dcrtc, static void armada_drm_vblank_off(struct armada_crtc *dcrtc) { - struct drm_device *dev = dcrtc->crtc.dev; + struct armada_frame_work *work; /* * Tell the DRM core that vblank IRQs aren't going to happen for @@ -302,10 +300,9 @@ static void armada_drm_vblank_off(struct armada_crtc *dcrtc) drm_crtc_vblank_off(&dcrtc->crtc); /* Handle any pending flip event. */ - spin_lock_irq(&dev->event_lock); - if (dcrtc->frame_work) - armada_drm_crtc_complete_frame_work(dcrtc); - spin_unlock_irq(&dev->event_lock); + work = xchg(&dcrtc->frame_work, NULL); + if (work) + armada_drm_crtc_complete_frame_work(dcrtc, work); } void armada_drm_crtc_gamma_set(struct drm_crtc *crtc, u16 r, u16 g, u16 b, @@ -434,12 +431,10 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) spin_unlock(&dcrtc->irq_lock); if (stat & GRA_FRAME_IRQ) { - struct drm_device *dev = dcrtc->crtc.dev; + struct armada_frame_work *work = xchg(&dcrtc->frame_work, NULL); - spin_lock(&dev->event_lock); - if (dcrtc->frame_work) - armada_drm_crtc_complete_frame_work(dcrtc); - spin_unlock(&dev->event_lock); + if (work) + armada_drm_crtc_complete_frame_work(dcrtc, work); wake_up(&dcrtc->frame_wait); } @@ -957,8 +952,6 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, { struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); struct armada_frame_work *work; - struct drm_device *dev = crtc->dev; - unsigned long flags; unsigned i; int ret; @@ -1004,10 +997,10 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, * interrupt, so complete it now. */ if (dpms_blanked(dcrtc->dpms)) { - spin_lock_irqsave(&dev->event_lock, flags); - if (dcrtc->frame_work) - armada_drm_crtc_complete_frame_work(dcrtc); - spin_unlock_irqrestore(&dev->event_lock, flags); + struct armada_frame_work *work = xchg(&dcrtc->frame_work, NULL); + + if (work) + armada_drm_crtc_complete_frame_work(dcrtc, work); } return 0;