Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/msm/mdp: Clear pending interrupt status before enable interrupt

Pending interrupt status needs to be cleared before enable the
interrupt. Otherwise it's possible to get a pending interrupt instead
of an incoming interrupt.

Signed-off-by: Jilai Wang <jilaiw@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>

authored by

jilai wang and committed by
Rob Clark
29f034d7 8089082f

+23 -10
+7 -3
drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
··· 19 19 #include "msm_drv.h" 20 20 #include "mdp4_kms.h" 21 21 22 - void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask) 22 + void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask, 23 + uint32_t old_irqmask) 23 24 { 25 + mdp4_write(to_mdp4_kms(mdp_kms), REG_MDP4_INTR_CLEAR, 26 + irqmask ^ (irqmask & old_irqmask)); 24 27 mdp4_write(to_mdp4_kms(mdp_kms), REG_MDP4_INTR_ENABLE, irqmask); 25 28 } 26 29 ··· 71 68 struct drm_device *dev = mdp4_kms->dev; 72 69 struct msm_drm_private *priv = dev->dev_private; 73 70 unsigned int id; 74 - uint32_t status; 71 + uint32_t status, enable; 75 72 76 - status = mdp4_read(mdp4_kms, REG_MDP4_INTR_STATUS); 73 + enable = mdp4_read(mdp4_kms, REG_MDP4_INTR_ENABLE); 74 + status = mdp4_read(mdp4_kms, REG_MDP4_INTR_STATUS) & enable; 77 75 mdp4_write(mdp4_kms, REG_MDP4_INTR_CLEAR, status); 78 76 79 77 VERB("status=%08x", status);
+2 -1
drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
··· 167 167 int mdp4_disable(struct mdp4_kms *mdp4_kms); 168 168 int mdp4_enable(struct mdp4_kms *mdp4_kms); 169 169 170 - void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask); 170 + void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask, 171 + uint32_t old_irqmask); 171 172 void mdp4_irq_preinstall(struct msm_kms *kms); 172 173 int mdp4_irq_postinstall(struct msm_kms *kms); 173 174 void mdp4_irq_uninstall(struct msm_kms *kms);
+7 -3
drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
··· 21 21 #include "msm_drv.h" 22 22 #include "mdp5_kms.h" 23 23 24 - void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask) 24 + void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask, 25 + uint32_t old_irqmask) 25 26 { 27 + mdp5_write(to_mdp5_kms(mdp_kms), REG_MDP5_MDP_INTR_CLEAR(0), 28 + irqmask ^ (irqmask & old_irqmask)); 26 29 mdp5_write(to_mdp5_kms(mdp_kms), REG_MDP5_MDP_INTR_EN(0), irqmask); 27 30 } 28 31 ··· 74 71 struct drm_device *dev = mdp5_kms->dev; 75 72 struct msm_drm_private *priv = dev->dev_private; 76 73 unsigned int id; 77 - uint32_t status; 74 + uint32_t status, enable; 78 75 79 - status = mdp5_read(mdp5_kms, REG_MDP5_MDP_INTR_STATUS(0)); 76 + enable = mdp5_read(mdp5_kms, REG_MDP5_MDP_INTR_EN(0)); 77 + status = mdp5_read(mdp5_kms, REG_MDP5_MDP_INTR_STATUS(0)) & enable; 80 78 mdp5_write(mdp5_kms, REG_MDP5_MDP_INTR_CLEAR(0), status); 81 79 82 80 VERB("status=%08x", status);
+2 -1
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
··· 186 186 int mdp5_disable(struct mdp5_kms *mdp5_kms); 187 187 int mdp5_enable(struct mdp5_kms *mdp5_kms); 188 188 189 - void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask); 189 + void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask, 190 + uint32_t old_irqmask); 190 191 void mdp5_irq_preinstall(struct msm_kms *kms); 191 192 int mdp5_irq_postinstall(struct msm_kms *kms); 192 193 void mdp5_irq_uninstall(struct msm_kms *kms);
+2 -1
drivers/gpu/drm/msm/mdp/mdp_kms.c
··· 39 39 list_for_each_entry(irq, &mdp_kms->irq_list, node) 40 40 irqmask |= irq->irqmask; 41 41 42 - mdp_kms->funcs->set_irqmask(mdp_kms, irqmask); 42 + mdp_kms->funcs->set_irqmask(mdp_kms, irqmask, mdp_kms->cur_irq_mask); 43 + mdp_kms->cur_irq_mask = irqmask; 43 44 } 44 45 45 46 /* if an mdp_irq's irqmask has changed, such as when mdp5 crtc<->encoder
+3 -1
drivers/gpu/drm/msm/mdp/mdp_kms.h
··· 30 30 31 31 struct mdp_kms_funcs { 32 32 struct msm_kms_funcs base; 33 - void (*set_irqmask)(struct mdp_kms *mdp_kms, uint32_t irqmask); 33 + void (*set_irqmask)(struct mdp_kms *mdp_kms, uint32_t irqmask, 34 + uint32_t old_irqmask); 34 35 }; 35 36 36 37 struct mdp_kms { ··· 43 42 bool in_irq; 44 43 struct list_head irq_list; /* list of mdp4_irq */ 45 44 uint32_t vblank_mask; /* irq bits set for userspace vblank */ 45 + uint32_t cur_irq_mask; /* current irq mask */ 46 46 }; 47 47 #define to_mdp_kms(x) container_of(x, struct mdp_kms, base) 48 48