dp_display_irq_handler() is the main isr handler with the helps
of two sub isr, dp_aux_isr and dp_ctrl_isr, to service all DP
interrupts on every irq triggered. Current all three isr does
not return IRQ_HANDLED if there are any interrupts it had
serviced. This patch fix this ambiguity by having all isr
return IRQ_HANDLED if there are interrupts had been serviced
or IRQ_NONE otherwise.

Changes in v5:
-- move complete into dp_aux_native_handler()
-- move complete into dp_aux_i2c_handler()
-- restore null ctrl check at isr
-- return IRQ_NODE directly

Signed-off-by: Kuogee Hsieh <quic_khs...@quicinc.com>
Suggested-by: Stephen Boyd <swb...@chromium.org>
---
 drivers/gpu/drm/msm/dp/dp_aux.c     | 95 ++++++++++++++++++++++++++-----------
 drivers/gpu/drm/msm/dp/dp_aux.h     |  2 +-
 drivers/gpu/drm/msm/dp/dp_ctrl.c    | 12 ++++-
 drivers/gpu/drm/msm/dp/dp_ctrl.h    |  2 +-
 drivers/gpu/drm/msm/dp/dp_display.c | 16 +++++--
 5 files changed, 89 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index cc3efed..d01ff45 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -162,45 +162,84 @@ 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;
        }
+
+       if (ret == IRQ_HANDLED)
+               complete(&aux->comp);
+
+       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;
+       }
+
+       if (ret == IRQ_HANDLED)
+               complete(&aux->comp);
+
+       return ret;
 }
 
 static void dp_aux_update_offset_and_segment(struct dp_aux_private *aux,
@@ -409,14 +448,14 @@ 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;
 
        if (!dp_aux) {
                DRM_ERROR("invalid input\n");
-               return;
+               return IRQ_NONE;
        }
 
        aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
@@ -425,17 +464,15 @@ void dp_aux_isr(struct drm_dp_aux *dp_aux)
 
        /* no interrupts pending, return immediately */
        if (!isr)
-               return;
+               return IRQ_NONE;
 
        if (!aux->cmd_busy)
-               return;
+               return IRQ_NONE;
 
        if (aux->native)
-               dp_aux_native_handler(aux, isr);
+               return dp_aux_native_handler(aux, isr);
        else
-               dp_aux_i2c_handler(aux, isr);
-
-       complete(&aux->comp);
+               return dp_aux_i2c_handler(aux, isr);
 }
 
 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 e930974..511305d 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 3854c9f..cb0acb1 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -1982,27 +1982,35 @@ 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;
+       irqreturn_t ret = IRQ_NONE;
 
        if (!dp_ctrl)
-               return;
+               return IRQ_NONE;
 
        ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
 
        isr = dp_catalog_ctrl_get_interrupt(ctrl->catalog);
+       /* no interrupts pending, return immediately */
+       if (!isr)
+               return IRQ_NONE;
 
        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 9f29734..c3af06d 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 bfd0aef..d40bfbd 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;
 }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

Reply via email to