diff options
| author | Thierry Reding <treding@nvidia.com> | 2014-12-16 10:33:27 -0500 |
|---|---|---|
| committer | Thierry Reding <treding@nvidia.com> | 2014-12-17 08:27:36 -0500 |
| commit | 6b59cc1c86e90cccf8fb0b4dee5fbc226bb82d3e (patch) | |
| tree | 4150f757c48d659fc7d1c6c15e64e8de2069fd66 | |
| parent | ed7dae58de246790f394caea5ef7eecad0e83387 (diff) | |
drm/tegra: dc: Fix a potential race on page-flip completion
Page-flip completion could race with page-flip submission, so extend the
critical section to include all accesses to page-flip related data.
Reported-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
| -rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 5a6d43dfeb8d..ef36f9d5e35e 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
| @@ -814,8 +814,12 @@ static void tegra_dc_finish_page_flip(struct tegra_dc *dc) | |||
| 814 | unsigned long flags, base; | 814 | unsigned long flags, base; |
| 815 | struct tegra_bo *bo; | 815 | struct tegra_bo *bo; |
| 816 | 816 | ||
| 817 | if (!dc->event) | 817 | spin_lock_irqsave(&drm->event_lock, flags); |
| 818 | |||
| 819 | if (!dc->event) { | ||
| 820 | spin_unlock_irqrestore(&drm->event_lock, flags); | ||
| 818 | return; | 821 | return; |
| 822 | } | ||
| 819 | 823 | ||
| 820 | bo = tegra_fb_get_plane(crtc->primary->fb, 0); | 824 | bo = tegra_fb_get_plane(crtc->primary->fb, 0); |
| 821 | 825 | ||
| @@ -825,12 +829,12 @@ static void tegra_dc_finish_page_flip(struct tegra_dc *dc) | |||
| 825 | tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS); | 829 | tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS); |
| 826 | 830 | ||
| 827 | if (base == bo->paddr + crtc->primary->fb->offsets[0]) { | 831 | if (base == bo->paddr + crtc->primary->fb->offsets[0]) { |
| 828 | spin_lock_irqsave(&drm->event_lock, flags); | ||
| 829 | drm_crtc_send_vblank_event(crtc, dc->event); | 832 | drm_crtc_send_vblank_event(crtc, dc->event); |
| 830 | drm_crtc_vblank_put(crtc); | 833 | drm_crtc_vblank_put(crtc); |
| 831 | dc->event = NULL; | 834 | dc->event = NULL; |
| 832 | spin_unlock_irqrestore(&drm->event_lock, flags); | ||
| 833 | } | 835 | } |
| 836 | |||
| 837 | spin_unlock_irqrestore(&drm->event_lock, flags); | ||
| 834 | } | 838 | } |
| 835 | 839 | ||
| 836 | void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) | 840 | void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) |
