aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r100.c
diff options
context:
space:
mode:
authorChristian Koenig <christian.koenig@amd.com>2012-05-16 19:33:30 -0400
committerChristian König <deathsimple@vodafone.de>2012-06-21 03:38:50 -0400
commitfb98257a9d9d2089972b18079d5bdd4412e107e2 (patch)
tree72f6115ccae023c1e6122bdd82cf310c8014de23 /drivers/gpu/drm/radeon/r100.c
parentc20dc3698dc7ecf053e2bf77299ae5982c0c2c45 (diff)
drm/radeon: apply Murphy's law to the kms irq code v3
1. It is really dangerous to have more than one spinlock protecting the same information. 2. radeon_irq_set sometimes wasn't called with lock protection, so it can happen that more than one CPU would tamper with the irq regs at the same time. 3. The pm.gui_idle variable was assuming that the 3D engine wasn't becoming idle between testing the register and setting the variable. So just remove it and test the register directly. v2: Also handle the hpd irq code the same way. v3: Rename hpd parameter for clarification. Signed-off-by: Christian Koenig <christian.koenig@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/r100.c')
-rw-r--r--drivers/gpu/drm/radeon/r100.c29
1 files changed, 6 insertions, 23 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 415b7d8fbba2..e8fe4ae3bc23 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -567,43 +567,27 @@ void r100_hpd_init(struct radeon_device *rdev)
567{ 567{
568 struct drm_device *dev = rdev->ddev; 568 struct drm_device *dev = rdev->ddev;
569 struct drm_connector *connector; 569 struct drm_connector *connector;
570 unsigned enable = 0;
570 571
571 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 572 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
572 struct radeon_connector *radeon_connector = to_radeon_connector(connector); 573 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
573 switch (radeon_connector->hpd.hpd) { 574 enable |= 1 << radeon_connector->hpd.hpd;
574 case RADEON_HPD_1:
575 rdev->irq.hpd[0] = true;
576 break;
577 case RADEON_HPD_2:
578 rdev->irq.hpd[1] = true;
579 break;
580 default:
581 break;
582 }
583 radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); 575 radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
584 } 576 }
585 if (rdev->irq.installed) 577 radeon_irq_kms_enable_hpd(rdev, enable);
586 r100_irq_set(rdev);
587} 578}
588 579
589void r100_hpd_fini(struct radeon_device *rdev) 580void r100_hpd_fini(struct radeon_device *rdev)
590{ 581{
591 struct drm_device *dev = rdev->ddev; 582 struct drm_device *dev = rdev->ddev;
592 struct drm_connector *connector; 583 struct drm_connector *connector;
584 unsigned disable = 0;
593 585
594 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 586 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
595 struct radeon_connector *radeon_connector = to_radeon_connector(connector); 587 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
596 switch (radeon_connector->hpd.hpd) { 588 disable |= 1 << radeon_connector->hpd.hpd;
597 case RADEON_HPD_1:
598 rdev->irq.hpd[0] = false;
599 break;
600 case RADEON_HPD_2:
601 rdev->irq.hpd[1] = false;
602 break;
603 default:
604 break;
605 }
606 } 589 }
590 radeon_irq_kms_disable_hpd(rdev, disable);
607} 591}
608 592
609/* 593/*
@@ -782,7 +766,6 @@ int r100_irq_process(struct radeon_device *rdev)
782 /* gui idle interrupt */ 766 /* gui idle interrupt */
783 if (status & RADEON_GUI_IDLE_STAT) { 767 if (status & RADEON_GUI_IDLE_STAT) {
784 rdev->irq.gui_idle_acked = true; 768 rdev->irq.gui_idle_acked = true;
785 rdev->pm.gui_idle = true;
786 wake_up(&rdev->irq.idle_queue); 769 wake_up(&rdev->irq.idle_queue);
787 } 770 }
788 /* Vertical blank interrupts */ 771 /* Vertical blank interrupts */