From patchwork Fri Oct 31 22:54:31 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve Longerbeam X-Patchwork-Id: 5207901 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.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 3D748C11AD for ; Fri, 31 Oct 2014 23:57:46 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 670A32010E for ; Fri, 31 Oct 2014 23:57:45 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 6FE4220173 for ; Fri, 31 Oct 2014 23:57:44 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 80E666E893; Fri, 31 Oct 2014 16:57:00 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-pd0-f181.google.com (mail-pd0-f181.google.com [209.85.192.181]) by gabe.freedesktop.org (Postfix) with ESMTP id DABD06E84A for ; Fri, 31 Oct 2014 15:57:27 -0700 (PDT) Received: by mail-pd0-f181.google.com with SMTP id y10so8088850pdj.40 for ; Fri, 31 Oct 2014 15:57:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=lMOIpLn+EmjqOWIoaXB89qxdxeDT8yfeAJQ9Culdh1w=; b=a67fMvGIu9TcPGYA/yOiQd2ljP2oSPW2ndp2KX1DALI/gCle7BGn0JrQNJP2KWLS9x LGJ8WDFbqD8Iyar8GnTjPPfxFCSzx/J5AkXQ79OIr4zoa5/yLoyVVl6SrVwyP5KApjxn JGme1Ufo2lSFxuDrGSq5G6j3xv+tCH0Rn+5tcsHblhN+A/PCX6XXRhqrNTYBAwIslPmz ANcKtwIPvf/4pLw2ebskSNf/azXGdGQR8Ip/HQfILck+c+FpdUm3IJKM+WSB8NoLZaWH t6qUNeUFI5Q4z9brV61PPRZjiIQyOKcxYuzcSpmloCHs8lWnEORnH6FSQ25elU5WfaMO wWAA== X-Received: by 10.68.89.129 with SMTP id bo1mr14759180pbb.46.1414796247760; Fri, 31 Oct 2014 15:57:27 -0700 (PDT) Received: from mothership.mgc.mentorg.com (c-50-152-159-227.hsd1.ca.comcast.net. [50.152.159.227]) by mx.google.com with ESMTPSA id ev8sm10870656pdb.28.2014.10.31.15.57.26 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 31 Oct 2014 15:57:27 -0700 (PDT) From: Steve Longerbeam X-Google-Original-From: Steve Longerbeam To: dri-devel@lists.freedesktop.org Subject: [PATCH 48/72] imx-drm: hdmi: rework irq request/free Date: Fri, 31 Oct 2014 15:54:31 -0700 Message-Id: <1414796095-10107-49-git-send-email-steve_longerbeam@mentor.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1414796095-10107-1-git-send-email-steve_longerbeam@mentor.com> References: <1414796095-10107-1-git-send-email-steve_longerbeam@mentor.com> X-Mailman-Approved-At: Fri, 31 Oct 2014 16:56:32 -0700 Cc: Dmitry Eremin-Solenikov 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: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, 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 Rearrange how HDMI driver requests and frees irq. Currently the driver has two problems: 1) if imx_hdmi_register() fails, irq still can trigger and cause oops 2) irq is enabled too early, before all fields are initialized, so triggered irq can cause oops. Fix by moving irq request and activation to very end of imx_hdmi_bind(), especially after imx_hdmi_register(). Then there's no possible way there could be a (spurious) interrupt after a failed imx_hdmi_register() but before the irq is freed. Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: Steve Longerbeam --- drivers/staging/imx-drm/imx-hdmi.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/staging/imx-drm/imx-hdmi.c b/drivers/staging/imx-drm/imx-hdmi.c index 801a3eb..db3906f 100644 --- a/drivers/staging/imx-drm/imx-hdmi.c +++ b/drivers/staging/imx-drm/imx-hdmi.c @@ -122,6 +122,7 @@ struct imx_hdmi { struct hdmi_data_info hdmi_data; int vic; + int irq; u8 edid[HDMI_EDID_LEN]; bool cable_plugin; @@ -1593,7 +1594,7 @@ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data) struct device_node *ddc_node; struct imx_hdmi *hdmi; struct resource *iores; - int ret, irq; + int ret; hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); if (!hdmi) @@ -1620,16 +1621,6 @@ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data) dev_dbg(hdmi->dev, "no ddc property found\n"); } - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - ret = devm_request_threaded_irq(dev, irq, imx_hdmi_hardirq, - imx_hdmi_irq, IRQF_SHARED, - dev_name(dev), hdmi); - if (ret) - return ret; - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); hdmi->regs = devm_ioremap_resource(dev, iores); if (IS_ERR(hdmi->regs)) @@ -1685,6 +1676,10 @@ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data) */ hdmi_init_clk_regenerator(hdmi); + ret = imx_hdmi_register(drm, hdmi); + if (ret) + goto err_isfr; + /* * Configure registers related to HDMI interrupt * generation before registering IRQ. @@ -1694,14 +1689,21 @@ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data) /* Clear Hotplug interrupts */ hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0); - ret = imx_hdmi_fb_registered(hdmi); - if (ret) + ret = platform_get_irq(pdev, 0); + if (ret < 0) goto err_iahb; + hdmi->irq = ret; - ret = imx_hdmi_register(drm, hdmi); + ret = devm_request_threaded_irq(dev, hdmi->irq, imx_hdmi_hardirq, + imx_hdmi_irq, IRQF_SHARED, + dev_name(dev), hdmi); if (ret) goto err_iahb; + ret = imx_hdmi_fb_registered(hdmi); + if (ret) + goto err_irq; + /* Unmute interrupts */ hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0); @@ -1709,6 +1711,8 @@ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data) return 0; +err_irq: + devm_free_irq(dev, hdmi->irq, hdmi); err_iahb: clk_disable_unprepare(hdmi->iahb_clk); err_isfr: @@ -1724,6 +1728,7 @@ static void imx_hdmi_unbind(struct device *dev, struct device *master, /* Disable all interrupts */ hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); + devm_free_irq(dev, hdmi->irq, hdmi); hdmi->connector.funcs->destroy(&hdmi->connector); hdmi->encoder.funcs->destroy(&hdmi->encoder);