From patchwork Tue Mar 24 12:15:50 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 6087411 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 52F59BF90F for ; Wed, 25 Mar 2015 03:21:09 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 66FEA2035C for ; Wed, 25 Mar 2015 03:21:08 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 3E0112037D for ; Wed, 25 Mar 2015 03:21:07 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 46841720B2; Tue, 24 Mar 2015 20:20:50 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from comal.ext.ti.com (comal.ext.ti.com [198.47.26.152]) by gabe.freedesktop.org (Postfix) with ESMTP id D9E1A6E6CA for ; Tue, 24 Mar 2015 05:16:56 -0700 (PDT) Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by comal.ext.ti.com (8.13.7/8.13.7) with ESMTP id t2OCGt64024857; Tue, 24 Mar 2015 07:16:55 -0500 Received: from DFLE73.ent.ti.com (dfle73.ent.ti.com [128.247.5.110]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id t2OCGrkH014484; Tue, 24 Mar 2015 07:16:54 -0500 Received: from dlep33.itg.ti.com (157.170.170.75) by DFLE73.ent.ti.com (128.247.5.110) with Microsoft SMTP Server id 14.3.224.2; Tue, 24 Mar 2015 07:16:53 -0500 Received: from deskari.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep33.itg.ti.com (8.14.3/8.13.8) with ESMTP id t2OCGCXi032032; Tue, 24 Mar 2015 07:16:53 -0500 From: Tomi Valkeinen To: Subject: [PATCH 33/36] drm/omap: fix race conditon in DMM Date: Tue, 24 Mar 2015 14:15:50 +0200 Message-ID: <1427199353-4412-34-git-send-email-tomi.valkeinen@ti.com> X-Mailer: git-send-email 2.3.3 In-Reply-To: <1427199353-4412-1-git-send-email-tomi.valkeinen@ti.com> References: <1427199353-4412-1-git-send-email-tomi.valkeinen@ti.com> MIME-Version: 1.0 X-Mailman-Approved-At: Tue, 24 Mar 2015 20:20:48 -0700 Cc: Tomi Valkeinen , Laurent Pinchart 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.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, 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 The omapdrm DMM code sometimes crashes with: WARNING: CPU: 0 PID: 1235 at lib/list_debug.c:36 __list_add+0x8c/0xbc() list_add double add: new=e9265368, prev=e90139c4, next=e9265368. This is caused by the code calling release_engine() twice for the same engine. dmm_txn_commit(wait=true) call is supposed to wait until the DMM transaction has been finished. And it does that, but it does not wait for the irq handler to finish. What happens is that the irq handler is triggered, and it either wakes up the thread that called dmm_txn_commit(), or that thread never even slept because the transaction was finished in the HW very quickly. That thread then continues executing, even if the irq handler is not yet finished, and a new transaction may be initiated. If that transaction is async (i.e. wait=false), a 'async' flag is set to true. The original irq handler, which has yet not finished, then sees the transaction as 'async', even if it was supposed to be 'sync'. When that happens, the irq handler does an extra release_engine() call because it thinks it need to release the engine, leading to the crash. This patch fixes the issue by using completion to ensure that the irq handler has finished before a dmm_txn_commit(wait=true) may continue. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_dmm_priv.h | 2 +- drivers/gpu/drm/omapdrm/omap_dmm_tiler.c | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_priv.h b/drivers/gpu/drm/omapdrm/omap_dmm_priv.h index d96660573076..9f32a83ca507 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_priv.h +++ b/drivers/gpu/drm/omapdrm/omap_dmm_priv.h @@ -148,7 +148,7 @@ struct refill_engine { bool async; - wait_queue_head_t wait_for_refill; + struct completion compl; struct list_head idle_node; }; diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c index a1a824db1dd6..20db850a1656 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "omap_dmm_tiler.h" #include "omap_dmm_priv.h" @@ -146,10 +147,10 @@ static irqreturn_t omap_dmm_irq_handler(int irq, void *arg) for (i = 0; i < dmm->num_engines; i++) { if (status & DMM_IRQSTAT_LST) { - wake_up_interruptible(&dmm->engines[i].wait_for_refill); - if (dmm->engines[i].async) release_engine(&dmm->engines[i]); + + complete(&dmm->engines[i].compl); } status >>= 8; @@ -273,7 +274,8 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait) /* mark whether it is async to denote list management in IRQ handler */ engine->async = wait ? false : true; - /* verify that the irq handler sees the 'async' value */ + reinit_completion(&engine->compl); + /* verify that the irq handler sees the 'async' and completion value */ smp_mb(); /* kick reload */ @@ -281,9 +283,8 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait) dmm->base + reg[PAT_DESCR][engine->id]); if (wait) { - if (wait_event_interruptible_timeout(engine->wait_for_refill, - wait_status(engine, DMM_PATSTATUS_READY) == 0, - msecs_to_jiffies(1)) <= 0) { + if (!wait_for_completion_timeout(&engine->compl, + msecs_to_jiffies(1))) { dev_err(dmm->dev, "timed out waiting for done\n"); ret = -ETIMEDOUT; } @@ -719,7 +720,7 @@ static int omap_dmm_probe(struct platform_device *dev) (REFILL_BUFFER_SIZE * i); omap_dmm->engines[i].refill_pa = omap_dmm->refill_pa + (REFILL_BUFFER_SIZE * i); - init_waitqueue_head(&omap_dmm->engines[i].wait_for_refill); + init_completion(&omap_dmm->engines[i].compl); list_add(&omap_dmm->engines[i].idle_node, &omap_dmm->idle_head); }