Received: by 2002:a05:6358:d09b:b0:dc:cd0c:909e with SMTP id jc27csp242890rwb; Wed, 14 Dec 2022 16:46:45 -0800 (PST) X-Google-Smtp-Source: AA0mqf4zjGYuEmCUt+KsZTOz3WaBcO+C3GdG736rsUJrla2NA3a1k1V0fWBeF7jrHxDHgsj8cvLN X-Received: by 2002:a17:90b:8ca:b0:219:6c99:828 with SMTP id ds10-20020a17090b08ca00b002196c990828mr28196466pjb.0.1671065205052; Wed, 14 Dec 2022 16:46:45 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1671065205; cv=none; d=google.com; s=arc-20160816; b=n4Skg3EYmYHLtqM0SHI9hcOmSCml8JAd9LxOvEcBbTsiLX1uaFn0JVjMlZ46KG1+D6 PSWvurBsXeD6w8U9Yl3Ui3T7KxNoOvvUU5O+zgyHc3OjR+97sDp9EuTYnQqPJ8UE7QjD RVyz8Kr8i3QAF7Ty19wKFiA8N2QamVMmfeMzuzOoJKU6XsTAlO0tSQJuo7L89c/ROFGt egZRvVMgz1edUXkNaaM4oM2Fr0fPS24lf3FLCyl6cFcDgtzGZeuUjrj9LZ1NgEFQBi6O 7+sNO7Qvs//fO1klzd08CEDnPiKcTDQpqs3kSdje8BTupSWA7iOD5r2goAr7uo4ZIbcz M4Cw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:subject:message-id:date:user-agent:from :references:in-reply-to:mime-version:dkim-signature; bh=B+38sfS9t514Rl7PsG77ovDyh44bJm6hQ/Gd7EYEdy4=; b=NCi8fxxGB7Al9vORPSc4rAis9OawDEbAmmLhBag8R2G7pHCOxSmm3NOYWecTSnLqKx evnwTVlzDi2ktYC4YDidmHC/+zwwodZ4ZhEyI+4qRqu7uA1Ypuzp8iiOX+ZUfKtJ5uXh +yA1sXKQy/wE939WDV/YqLuunjYAqJsnzbEGxFxbHCEdj2cyPYAfvyRoFzISImQZ9iVs 7ITjCfUy07tQNf0JfWTM1Iy9e/b8G8fM+8hDmsyXTeSuNDTlYR7G997Vxt9TV8QYBBgl GYhuMgXyw792plPR8lqUeC0CO3PoeraCHjSXxZ+ifXjVWXLVEJHGkPRwoI6Cn+KPKNAl hiAw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=fd2EsDcc; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ob8-20020a17090b390800b002197ff12d35si3701172pjb.25.2022.12.14.16.46.35; Wed, 14 Dec 2022 16:46:45 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=fd2EsDcc; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229791AbiLOA3d (ORCPT + 69 others); Wed, 14 Dec 2022 19:29:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46454 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229634AbiLOA3b (ORCPT ); Wed, 14 Dec 2022 19:29:31 -0500 Received: from mail-lf1-x135.google.com (mail-lf1-x135.google.com [IPv6:2a00:1450:4864:20::135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E2C442CE23 for ; Wed, 14 Dec 2022 16:29:28 -0800 (PST) Received: by mail-lf1-x135.google.com with SMTP id y25so13185322lfa.9 for ; Wed, 14 Dec 2022 16:29:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=cc:to:subject:message-id:date:user-agent:from:references :in-reply-to:mime-version:from:to:cc:subject:date:message-id :reply-to; bh=B+38sfS9t514Rl7PsG77ovDyh44bJm6hQ/Gd7EYEdy4=; b=fd2EsDccm2rXlUqIolwjM5UgqzJIqI73gqkHE/9dJylKnXV87gefUcdBf9HRc9n8CI EwyuQ60o7BHXN4xMPhfxLQoyrGmi92Dersf9uAfT8Kx4VwRfZqeoKe/mzdlBTZ4dwXun 0a8aUClNbuJPGRtqNePGOoy8Z4sZbqGpOdmV0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:user-agent:from:references :in-reply-to:mime-version:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=B+38sfS9t514Rl7PsG77ovDyh44bJm6hQ/Gd7EYEdy4=; b=0sXZpLR11lVmdrcgcpiop+347jdDnAGvGs+dtIDlsMmlWJaaGYly6Xw3+XiZgs0dKb YylUXqGogMseXsBF97ecK4+ayVAt6bewuNO+4nIEOxJaO2ukAjiRm9OLIWgTWO0Qtzi2 FDYR/QXWGgqs6Nyy7ot3O2gFHm1+GM1foZIIVTEyWeyDIKHbswp4Syh4NHVdWiK0Weul zfsOvyqnndhWtwRBxadK1/JXx4fgMu3jpLs8hhpDMJxae+EQMPg2d53eO7kw1zUjqTIP VgHrMfmhwiuKfKz1Hcbu/ez8J5DqX0zXNtufLN/1Kezm+PSq/U9nYb2+SKisnTL19rdu XAcw== X-Gm-Message-State: ANoB5plvXOrZhJJN7QUTU4xelOMRuRtwPI1egkwyYoLLjoii5v7hB5+a nyD2YUETMNE6OnQaLU6RprpRzr6uzHV4XhRm/0l61g== X-Received: by 2002:a05:6512:b98:b0:4b5:5f2d:1458 with SMTP id b24-20020a0565120b9800b004b55f2d1458mr7850915lfv.253.1671064167154; Wed, 14 Dec 2022 16:29:27 -0800 (PST) Received: from 753933720722 named unknown by gmailapi.google.com with HTTPREST; Wed, 14 Dec 2022 19:29:26 -0500 MIME-Version: 1.0 In-Reply-To: References: <1671052890-11627-1-git-send-email-quic_khsieh@quicinc.com> <512f9f0d-a399-27fb-08d0-7311b73fd2a1@quicinc.com> From: Stephen Boyd User-Agent: alot/0.10 Date: Wed, 14 Dec 2022 19:29:26 -0500 Message-ID: Subject: Re: [PATCH] drm/msm/dp: do not complete dp_aux_cmd_fifo_tx() if irq is not for aux transfer To: Abhinav Kumar , Doug Anderson Cc: Kuogee Hsieh , robdclark@gmail.com, sean@poorly.run, vkoul@kernel.org, daniel@ffwll.ch, airlied@gmail.com, agross@kernel.org, dmitry.baryshkov@linaro.org, andersson@kernel.org, quic_sbillaka@quicinc.com, freedreno@lists.freedesktop.org, dri-devel@lists.freedesktop.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Quoting Doug Anderson (2022-12-14 16:14:42) > Hi, > > On Wed, Dec 14, 2022 at 3:46 PM Abhinav Kumar wrote: > > > > Hi Doug > > > > On 12/14/2022 2:29 PM, Doug Anderson wrote: > > > Hi, > > > > > > On Wed, Dec 14, 2022 at 1:21 PM Kuogee Hsieh wrote: > > >> > > >> There are 3 possible interrupt sources are handled by DP controller, > > >> HPDstatus, Controller state changes and Aux read/write transaction. > > >> At every irq, DP controller have to check isr status of every interrupt > > >> sources and service the interrupt if its isr status bits shows interrupts > > >> are pending. There is potential race condition may happen at current aux > > >> isr handler implementation since it is always complete dp_aux_cmd_fifo_tx() > > >> even irq is not for aux read or write transaction. This may cause aux read > > >> transaction return premature if host aux data read is in the middle of > > >> waiting for sink to complete transferring data to host while irq happen. > > >> This will cause host's receiving buffer contains unexpected data. This > > >> patch fixes this problem by checking aux isr and return immediately at > > >> aux isr handler if there are no any isr status bits set. > > >> > > >> Follows are the signature at kernel logs when problem happen, > > >> EDID has corrupt header > > >> panel-simple-dp-aux aux-aea0000.edp: Couldn't identify panel via EDID > > >> panel-simple-dp-aux aux-aea0000.edp: error -EIO: Couldn't detect panel nor find a fallback > > >> > > >> Signed-off-by: Kuogee Hsieh > > >> --- > > >> drivers/gpu/drm/msm/dp/dp_aux.c | 7 +++++++ > > >> 1 file changed, 7 insertions(+) > > >> > > >> diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c > > >> index d030a93..8f8b12a 100644 > > >> --- a/drivers/gpu/drm/msm/dp/dp_aux.c > > >> +++ b/drivers/gpu/drm/msm/dp/dp_aux.c > > >> @@ -423,6 +423,13 @@ void dp_aux_isr(struct drm_dp_aux *dp_aux) > > >> > > >> isr = dp_catalog_aux_get_irq(aux->catalog); > > >> > > >> + /* > > >> + * if this irq is not for aux transfer, > > >> + * then return immediately > > >> + */ > > > > > > Why do you need 4 lines for a comment that fits on one line? > > Yes, we can fit this to one line. > > > > > >> + if (!isr) > > >> + return; > > > > > > I can confirm that this works for me. I could reproduce the EDID > > > problems in the past and I can't after this patch. ...so I could give > > > a: > > > > > > Tested-by: Douglas Anderson > > > > > > I'm not an expert on this part of the code, so feel free to ignore my > > > other comments if everyone else thinks this patch is fine as-is, but > > > to me something here feels a little fragile. It feels a little weird > > > that we'll "complete" for _any_ interrupt that comes through now > > > rather than relying on dp_aux_native_handler() / dp_aux_i2c_handler() > > > to specifically identify interrupts that caused the end of the > > > transfer. I guess that idea is that every possible interrupt we get > > > causes the end of the transfer? > > > > > > -Doug > > > > So this turned out to be more tricky and was a good finding from kuogee. > > > > In the bad EDID case, it was technically not bad EDID. > > > > What was happening was, the VIDEO_READY interrupt was continuously > > firing. Ideally, this should fire only once but due to some error > > condition it kept firing. We dont exactly know why yet what was the > > error condition making it continuously fire. This is a great detail that is missing from the commit text. > > > > In the DP ISR, the dp_aux_isr() gets called even if it was not an aux > > interrupt which fired (so the call flow in this case was > > dp_display_irq_handler (triggered for VIDEO_READY) ---> dp_aux_isr() > > So we should certainly have some protection to return early from this > > routine if there was no aux interrupt which fired. I'm not sure that's a race condition though, more like a problem where the completion is called unconditionally? > > > > Which is what this fix is doing. > > > > Its not completing any interrupt, its just returning early if no aux > > interrupt fired. > > ...but the whole problem was that it was doing the complete() at the > end, right? Kuogee even mentioned that in the commit message. > Specifically, I checked dp_aux_native_handler() and > dp_aux_i2c_handler(), both of which are passed the "isr". Unless I > messed up, both functions already were no-ops if the ISR was 0, even > before Kuogee's patch. That means that the only thing Kuogee's patch > does is to prevent the call to "complete(&aux->comp)" at the end of > "dp_aux_isr()". > > ...and it makes sense not to call the complete() if no "isr" is 0. > ...but what I'm saying is that _any_ non-zero value of ISR will still > cause the complete() to be called after Kuogee's patch. That means > that if any of the 32-bits in the "isr" variable are set, that we will > call complete(). I'm asking if you're sure that every single bit of > the "isr" means that we're ready to call complete(). It feels like it > would be less fragile if dp_aux_native_handler() and > dp_aux_i2c_handler() (which both already look at the ISR) returned > some value saying whether the "isr" contained a bit that meant that > complete() should be called. > I'm almost certain I've asked for this before, but I can't find it anymore. Can we also simplify the aux handlers to be a big pile of if-else-if conditions that don't overwrite the 'aux_error_num'? That would simplify the patch below. ---8<--- diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c index d030a93a08c3..ff79cad90d21 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.c +++ b/drivers/gpu/drm/msm/dp/dp_aux.c @@ -162,45 +162,73 @@ static ssize_t dp_aux_cmd_fifo_rx(struct dp_aux_private *aux, return i; } -static void dp_aux_native_handler(struct dp_aux_private *aux, u32 isr) +static irqreturn_t dp_aux_native_handler(struct dp_aux_private *aux, u32 isr) { - if (isr & DP_INTR_AUX_I2C_DONE) + irqreturn_t ret = IRQ_NONE; + + if (isr & DP_INTR_AUX_I2C_DONE) { aux->aux_error_num = DP_AUX_ERR_NONE; - else if (isr & DP_INTR_WRONG_ADDR) + ret = IRQ_HANDLED; + } else if (isr & DP_INTR_WRONG_ADDR) { aux->aux_error_num = DP_AUX_ERR_ADDR; - else if (isr & DP_INTR_TIMEOUT) + ret = IRQ_HANDLED; + } else if (isr & DP_INTR_TIMEOUT) { aux->aux_error_num = DP_AUX_ERR_TOUT; - if (isr & DP_INTR_NACK_DEFER) + ret = IRQ_HANDLED; + } + + if (isr & DP_INTR_NACK_DEFER) { aux->aux_error_num = DP_AUX_ERR_NACK; + ret = IRQ_HANDLED; + } if (isr & DP_INTR_AUX_ERROR) { aux->aux_error_num = DP_AUX_ERR_PHY; dp_catalog_aux_clear_hw_interrupts(aux->catalog); + ret = IRQ_HANDLED; } + + return ret; } -static void dp_aux_i2c_handler(struct dp_aux_private *aux, u32 isr) +static irqreturn_t dp_aux_i2c_handler(struct dp_aux_private *aux, u32 isr) { + irqreturn_t ret = IRQ_NONE; + if (isr & DP_INTR_AUX_I2C_DONE) { if (isr & (DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER)) aux->aux_error_num = DP_AUX_ERR_NACK; else aux->aux_error_num = DP_AUX_ERR_NONE; - } else { - if (isr & DP_INTR_WRONG_ADDR) - aux->aux_error_num = DP_AUX_ERR_ADDR; - else if (isr & DP_INTR_TIMEOUT) - aux->aux_error_num = DP_AUX_ERR_TOUT; - if (isr & DP_INTR_NACK_DEFER) - aux->aux_error_num = DP_AUX_ERR_NACK_DEFER; - if (isr & DP_INTR_I2C_NACK) - aux->aux_error_num = DP_AUX_ERR_NACK; - if (isr & DP_INTR_I2C_DEFER) - aux->aux_error_num = DP_AUX_ERR_DEFER; - if (isr & DP_INTR_AUX_ERROR) { - aux->aux_error_num = DP_AUX_ERR_PHY; - dp_catalog_aux_clear_hw_interrupts(aux->catalog); - } + return IRQ_HANDLED; + } + + if (isr & DP_INTR_WRONG_ADDR) { + aux->aux_error_num = DP_AUX_ERR_ADDR; + ret = IRQ_HANDLED; + } else if (isr & DP_INTR_TIMEOUT) { + aux->aux_error_num = DP_AUX_ERR_TOUT; + ret = IRQ_HANDLED; + } + + if (isr & DP_INTR_NACK_DEFER) { + aux->aux_error_num = DP_AUX_ERR_NACK_DEFER; + ret = IRQ_HANDLED; + } + if (isr & DP_INTR_I2C_NACK) { + aux->aux_error_num = DP_AUX_ERR_NACK; + ret = IRQ_HANDLED; + } + if (isr & DP_INTR_I2C_DEFER) { + aux->aux_error_num = DP_AUX_ERR_DEFER; + ret = IRQ_HANDLED; + } + if (isr & DP_INTR_AUX_ERROR) { + aux->aux_error_num = DP_AUX_ERR_PHY; + dp_catalog_aux_clear_hw_interrupts(aux->catalog); + ret = IRQ_HANDLED; } + + return ret; } static void dp_aux_update_offset_and_segment(struct dp_aux_private *aux, @@ -409,14 +437,15 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, return ret; } -void dp_aux_isr(struct drm_dp_aux *dp_aux) +irqreturn_t dp_aux_isr(struct drm_dp_aux *dp_aux) { u32 isr; struct dp_aux_private *aux; + irqreturn_t ret = IRQ_NONE; if (!dp_aux) { DRM_ERROR("invalid input\n"); - return; + return ret; } aux = container_of(dp_aux, struct dp_aux_private, dp_aux); @@ -424,14 +453,17 @@ void dp_aux_isr(struct drm_dp_aux *dp_aux) isr = dp_catalog_aux_get_irq(aux->catalog); if (!aux->cmd_busy) - return; + return ret; if (aux->native) - dp_aux_native_handler(aux, isr); + ret |= dp_aux_native_handler(aux, isr); else - dp_aux_i2c_handler(aux, isr); + ret |= dp_aux_i2c_handler(aux, isr); - complete(&aux->comp); + if (ret == IRQ_HANDLED) + complete(&aux->comp); + + return ret; } void dp_aux_reconfig(struct drm_dp_aux *dp_aux) diff --git a/drivers/gpu/drm/msm/dp/dp_aux.h b/drivers/gpu/drm/msm/dp/dp_aux.h index e930974bcb5b..511305da4f66 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.h +++ b/drivers/gpu/drm/msm/dp/dp_aux.h @@ -11,7 +11,7 @@ int dp_aux_register(struct drm_dp_aux *dp_aux); void dp_aux_unregister(struct drm_dp_aux *dp_aux); -void dp_aux_isr(struct drm_dp_aux *dp_aux); +irqreturn_t dp_aux_isr(struct drm_dp_aux *dp_aux); void dp_aux_init(struct drm_dp_aux *dp_aux); void dp_aux_deinit(struct drm_dp_aux *dp_aux); void dp_aux_reconfig(struct drm_dp_aux *dp_aux); diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index dd26ca651a05..10c6d6847163 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1979,13 +1979,11 @@ int dp_ctrl_off(struct dp_ctrl *dp_ctrl) return ret; } -void dp_ctrl_isr(struct dp_ctrl *dp_ctrl) +irqreturn_t dp_ctrl_isr(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; u32 isr; - - if (!dp_ctrl) - return; + irqreturn_t ret = IRQ_NONE; ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); @@ -1994,12 +1992,16 @@ void dp_ctrl_isr(struct dp_ctrl *dp_ctrl) if (isr & DP_CTRL_INTR_READY_FOR_VIDEO) { drm_dbg_dp(ctrl->drm_dev, "dp_video_ready\n"); complete(&ctrl->video_comp); + ret = IRQ_HANDLED; } if (isr & DP_CTRL_INTR_IDLE_PATTERN_SENT) { drm_dbg_dp(ctrl->drm_dev, "idle_patterns_sent\n"); complete(&ctrl->idle_comp); + ret = IRQ_HANDLED; } + + return ret; } struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link, diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 9f29734af81c..c3af06dc87b1 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -25,7 +25,7 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl); int dp_ctrl_off_link(struct dp_ctrl *dp_ctrl); int dp_ctrl_off(struct dp_ctrl *dp_ctrl); void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl); -void dp_ctrl_isr(struct dp_ctrl *dp_ctrl); +irqreturn_t dp_ctrl_isr(struct dp_ctrl *dp_ctrl); void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl); struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link, struct dp_panel *panel, struct drm_dp_aux *aux, diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index a49f6dbbe888..559d9ab7954d 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1192,7 +1192,7 @@ static int dp_hpd_event_thread_start(struct dp_display_private *dp_priv) static irqreturn_t dp_display_irq_handler(int irq, void *dev_id) { struct dp_display_private *dp = dev_id; - irqreturn_t ret = IRQ_HANDLED; + irqreturn_t ret = IRQ_NONE; u32 hpd_isr_status; if (!dp) { @@ -1206,27 +1206,33 @@ static irqreturn_t dp_display_irq_handler(int irq, void *dev_id) drm_dbg_dp(dp->drm_dev, "type=%d isr=0x%x\n", dp->dp_display.connector_type, hpd_isr_status); /* hpd related interrupts */ - if (hpd_isr_status & DP_DP_HPD_PLUG_INT_MASK) + if (hpd_isr_status & DP_DP_HPD_PLUG_INT_MASK) { dp_add_event(dp, EV_HPD_PLUG_INT, 0, 0); + ret = IRQ_HANDLED; + } if (hpd_isr_status & DP_DP_IRQ_HPD_INT_MASK) { dp_add_event(dp, EV_IRQ_HPD_INT, 0, 0); + ret = IRQ_HANDLED; } if (hpd_isr_status & DP_DP_HPD_REPLUG_INT_MASK) { dp_add_event(dp, EV_HPD_UNPLUG_INT, 0, 0); dp_add_event(dp, EV_HPD_PLUG_INT, 0, 3); + ret = IRQ_HANDLED; } - if (hpd_isr_status & DP_DP_HPD_UNPLUG_INT_MASK) + if (hpd_isr_status & DP_DP_HPD_UNPLUG_INT_MASK) { dp_add_event(dp, EV_HPD_UNPLUG_INT, 0, 0); + ret = IRQ_HANDLED; + } } /* DP controller isr */ - dp_ctrl_isr(dp->ctrl); + ret |= dp_ctrl_isr(dp->ctrl); /* DP aux isr */ - dp_aux_isr(dp->aux); + ret |= dp_aux_isr(dp->aux); return ret; }