mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-12 13:34:10 +08:00
drm/radeon: use system_wq instead of dev_priv->wq
With cmwq, there's no reason for radeon to use a dedicated workqueue. Drop dev_priv->wq and use system_wq instead. Because radeon_driver_irq_uninstall_kms() may be called from unsleepable context, the work items can't be flushed from there. Instead, init and flush from radeon_irq_kms_init/fini(). While at it, simplify canceling/flushing of rdev->pm.dynpm_idle_work. Always initialize and sync cancel instead of being unnecessarily smart about it. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Alex Deucher <alexdeucher@gmail.com> Cc: dri-devel@lists.freedesktop.org Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
af5dd83b87
commit
32c87fca2f
@ -2756,7 +2756,7 @@ restart_ih:
|
|||||||
if (wptr != rdev->ih.wptr)
|
if (wptr != rdev->ih.wptr)
|
||||||
goto restart_ih;
|
goto restart_ih;
|
||||||
if (queue_hotplug)
|
if (queue_hotplug)
|
||||||
queue_work(rdev->wq, &rdev->hotplug_work);
|
schedule_work(&rdev->hotplug_work);
|
||||||
rdev->ih.rptr = rptr;
|
rdev->ih.rptr = rptr;
|
||||||
WREG32(IH_RB_RPTR, rdev->ih.rptr);
|
WREG32(IH_RB_RPTR, rdev->ih.rptr);
|
||||||
spin_unlock_irqrestore(&rdev->ih.lock, flags);
|
spin_unlock_irqrestore(&rdev->ih.lock, flags);
|
||||||
|
@ -682,7 +682,7 @@ int r100_irq_process(struct radeon_device *rdev)
|
|||||||
/* reset gui idle ack. the status bit is broken */
|
/* reset gui idle ack. the status bit is broken */
|
||||||
rdev->irq.gui_idle_acked = false;
|
rdev->irq.gui_idle_acked = false;
|
||||||
if (queue_hotplug)
|
if (queue_hotplug)
|
||||||
queue_work(rdev->wq, &rdev->hotplug_work);
|
schedule_work(&rdev->hotplug_work);
|
||||||
if (rdev->msi_enabled) {
|
if (rdev->msi_enabled) {
|
||||||
switch (rdev->family) {
|
switch (rdev->family) {
|
||||||
case CHIP_RS400:
|
case CHIP_RS400:
|
||||||
|
@ -3442,7 +3442,7 @@ restart_ih:
|
|||||||
if (wptr != rdev->ih.wptr)
|
if (wptr != rdev->ih.wptr)
|
||||||
goto restart_ih;
|
goto restart_ih;
|
||||||
if (queue_hotplug)
|
if (queue_hotplug)
|
||||||
queue_work(rdev->wq, &rdev->hotplug_work);
|
schedule_work(&rdev->hotplug_work);
|
||||||
rdev->ih.rptr = rptr;
|
rdev->ih.rptr = rptr;
|
||||||
WREG32(IH_RB_RPTR, rdev->ih.rptr);
|
WREG32(IH_RB_RPTR, rdev->ih.rptr);
|
||||||
spin_unlock_irqrestore(&rdev->ih.lock, flags);
|
spin_unlock_irqrestore(&rdev->ih.lock, flags);
|
||||||
|
@ -1152,7 +1152,6 @@ struct radeon_device {
|
|||||||
struct r700_vram_scratch vram_scratch;
|
struct r700_vram_scratch vram_scratch;
|
||||||
int msi_enabled; /* msi enabled */
|
int msi_enabled; /* msi enabled */
|
||||||
struct r600_ih ih; /* r6/700 interrupt ring */
|
struct r600_ih ih; /* r6/700 interrupt ring */
|
||||||
struct workqueue_struct *wq;
|
|
||||||
struct work_struct hotplug_work;
|
struct work_struct hotplug_work;
|
||||||
int num_crtc; /* number of crtcs */
|
int num_crtc; /* number of crtcs */
|
||||||
struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
|
struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
|
||||||
|
@ -710,11 +710,6 @@ int radeon_device_init(struct radeon_device *rdev,
|
|||||||
init_waitqueue_head(&rdev->irq.vblank_queue);
|
init_waitqueue_head(&rdev->irq.vblank_queue);
|
||||||
init_waitqueue_head(&rdev->irq.idle_queue);
|
init_waitqueue_head(&rdev->irq.idle_queue);
|
||||||
|
|
||||||
/* setup workqueue */
|
|
||||||
rdev->wq = create_workqueue("radeon");
|
|
||||||
if (rdev->wq == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
/* Set asic functions */
|
/* Set asic functions */
|
||||||
r = radeon_asic_init(rdev);
|
r = radeon_asic_init(rdev);
|
||||||
if (r)
|
if (r)
|
||||||
@ -813,7 +808,6 @@ void radeon_device_fini(struct radeon_device *rdev)
|
|||||||
/* evict vram memory */
|
/* evict vram memory */
|
||||||
radeon_bo_evict_vram(rdev);
|
radeon_bo_evict_vram(rdev);
|
||||||
radeon_fini(rdev);
|
radeon_fini(rdev);
|
||||||
destroy_workqueue(rdev->wq);
|
|
||||||
vga_switcheroo_unregister_client(rdev->pdev);
|
vga_switcheroo_unregister_client(rdev->pdev);
|
||||||
vga_client_register(rdev->pdev, NULL, NULL, NULL);
|
vga_client_register(rdev->pdev, NULL, NULL, NULL);
|
||||||
if (rdev->rio_mem)
|
if (rdev->rio_mem)
|
||||||
|
@ -64,8 +64,6 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
|
|||||||
struct radeon_device *rdev = dev->dev_private;
|
struct radeon_device *rdev = dev->dev_private;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
|
|
||||||
|
|
||||||
/* Disable *all* interrupts */
|
/* Disable *all* interrupts */
|
||||||
rdev->irq.sw_int = false;
|
rdev->irq.sw_int = false;
|
||||||
rdev->irq.gui_idle = false;
|
rdev->irq.gui_idle = false;
|
||||||
@ -114,6 +112,8 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
|
|||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
|
INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
|
||||||
|
|
||||||
spin_lock_init(&rdev->irq.sw_lock);
|
spin_lock_init(&rdev->irq.sw_lock);
|
||||||
r = drm_vblank_init(rdev->ddev, rdev->num_crtc);
|
r = drm_vblank_init(rdev->ddev, rdev->num_crtc);
|
||||||
if (r) {
|
if (r) {
|
||||||
@ -152,6 +152,7 @@ void radeon_irq_kms_fini(struct radeon_device *rdev)
|
|||||||
if (rdev->msi_enabled)
|
if (rdev->msi_enabled)
|
||||||
pci_disable_msi(rdev->pdev);
|
pci_disable_msi(rdev->pdev);
|
||||||
}
|
}
|
||||||
|
flush_work_sync(&rdev->hotplug_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev)
|
void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev)
|
||||||
|
@ -405,20 +405,13 @@ static ssize_t radeon_set_pm_method(struct device *dev,
|
|||||||
rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
|
rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
|
||||||
mutex_unlock(&rdev->pm.mutex);
|
mutex_unlock(&rdev->pm.mutex);
|
||||||
} else if (strncmp("profile", buf, strlen("profile")) == 0) {
|
} else if (strncmp("profile", buf, strlen("profile")) == 0) {
|
||||||
bool flush_wq = false;
|
|
||||||
|
|
||||||
mutex_lock(&rdev->pm.mutex);
|
mutex_lock(&rdev->pm.mutex);
|
||||||
if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
|
|
||||||
cancel_delayed_work(&rdev->pm.dynpm_idle_work);
|
|
||||||
flush_wq = true;
|
|
||||||
}
|
|
||||||
/* disable dynpm */
|
/* disable dynpm */
|
||||||
rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
|
rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
|
||||||
rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
|
rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
|
||||||
rdev->pm.pm_method = PM_METHOD_PROFILE;
|
rdev->pm.pm_method = PM_METHOD_PROFILE;
|
||||||
mutex_unlock(&rdev->pm.mutex);
|
mutex_unlock(&rdev->pm.mutex);
|
||||||
if (flush_wq)
|
cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
|
||||||
flush_workqueue(rdev->wq);
|
|
||||||
} else {
|
} else {
|
||||||
DRM_ERROR("invalid power method!\n");
|
DRM_ERROR("invalid power method!\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -524,18 +517,14 @@ static void radeon_hwmon_fini(struct radeon_device *rdev)
|
|||||||
|
|
||||||
void radeon_pm_suspend(struct radeon_device *rdev)
|
void radeon_pm_suspend(struct radeon_device *rdev)
|
||||||
{
|
{
|
||||||
bool flush_wq = false;
|
|
||||||
|
|
||||||
mutex_lock(&rdev->pm.mutex);
|
mutex_lock(&rdev->pm.mutex);
|
||||||
if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
|
if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
|
||||||
cancel_delayed_work(&rdev->pm.dynpm_idle_work);
|
|
||||||
if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
|
if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
|
||||||
rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
|
rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
|
||||||
flush_wq = true;
|
|
||||||
}
|
}
|
||||||
mutex_unlock(&rdev->pm.mutex);
|
mutex_unlock(&rdev->pm.mutex);
|
||||||
if (flush_wq)
|
|
||||||
flush_workqueue(rdev->wq);
|
cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
void radeon_pm_resume(struct radeon_device *rdev)
|
void radeon_pm_resume(struct radeon_device *rdev)
|
||||||
@ -550,8 +539,8 @@ void radeon_pm_resume(struct radeon_device *rdev)
|
|||||||
if (rdev->pm.pm_method == PM_METHOD_DYNPM
|
if (rdev->pm.pm_method == PM_METHOD_DYNPM
|
||||||
&& rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
|
&& rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
|
||||||
rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
|
rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
|
||||||
queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
|
schedule_delayed_work(&rdev->pm.dynpm_idle_work,
|
||||||
msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
|
msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
|
||||||
}
|
}
|
||||||
mutex_unlock(&rdev->pm.mutex);
|
mutex_unlock(&rdev->pm.mutex);
|
||||||
radeon_pm_compute_clocks(rdev);
|
radeon_pm_compute_clocks(rdev);
|
||||||
@ -585,6 +574,9 @@ int radeon_pm_init(struct radeon_device *rdev)
|
|||||||
ret = radeon_hwmon_init(rdev);
|
ret = radeon_hwmon_init(rdev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
INIT_DELAYED_WORK(&rdev->pm.dynpm_idle_work, radeon_dynpm_idle_work_handler);
|
||||||
|
|
||||||
if (rdev->pm.num_power_states > 1) {
|
if (rdev->pm.num_power_states > 1) {
|
||||||
/* where's the best place to put these? */
|
/* where's the best place to put these? */
|
||||||
ret = device_create_file(rdev->dev, &dev_attr_power_profile);
|
ret = device_create_file(rdev->dev, &dev_attr_power_profile);
|
||||||
@ -598,8 +590,6 @@ int radeon_pm_init(struct radeon_device *rdev)
|
|||||||
rdev->acpi_nb.notifier_call = radeon_acpi_event;
|
rdev->acpi_nb.notifier_call = radeon_acpi_event;
|
||||||
register_acpi_notifier(&rdev->acpi_nb);
|
register_acpi_notifier(&rdev->acpi_nb);
|
||||||
#endif
|
#endif
|
||||||
INIT_DELAYED_WORK(&rdev->pm.dynpm_idle_work, radeon_dynpm_idle_work_handler);
|
|
||||||
|
|
||||||
if (radeon_debugfs_pm_init(rdev)) {
|
if (radeon_debugfs_pm_init(rdev)) {
|
||||||
DRM_ERROR("Failed to register debugfs file for PM!\n");
|
DRM_ERROR("Failed to register debugfs file for PM!\n");
|
||||||
}
|
}
|
||||||
@ -613,25 +603,20 @@ int radeon_pm_init(struct radeon_device *rdev)
|
|||||||
void radeon_pm_fini(struct radeon_device *rdev)
|
void radeon_pm_fini(struct radeon_device *rdev)
|
||||||
{
|
{
|
||||||
if (rdev->pm.num_power_states > 1) {
|
if (rdev->pm.num_power_states > 1) {
|
||||||
bool flush_wq = false;
|
|
||||||
|
|
||||||
mutex_lock(&rdev->pm.mutex);
|
mutex_lock(&rdev->pm.mutex);
|
||||||
if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
|
if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
|
||||||
rdev->pm.profile = PM_PROFILE_DEFAULT;
|
rdev->pm.profile = PM_PROFILE_DEFAULT;
|
||||||
radeon_pm_update_profile(rdev);
|
radeon_pm_update_profile(rdev);
|
||||||
radeon_pm_set_clocks(rdev);
|
radeon_pm_set_clocks(rdev);
|
||||||
} else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
|
} else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
|
||||||
/* cancel work */
|
|
||||||
cancel_delayed_work(&rdev->pm.dynpm_idle_work);
|
|
||||||
flush_wq = true;
|
|
||||||
/* reset default clocks */
|
/* reset default clocks */
|
||||||
rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
|
rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
|
||||||
rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
|
rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
|
||||||
radeon_pm_set_clocks(rdev);
|
radeon_pm_set_clocks(rdev);
|
||||||
}
|
}
|
||||||
mutex_unlock(&rdev->pm.mutex);
|
mutex_unlock(&rdev->pm.mutex);
|
||||||
if (flush_wq)
|
|
||||||
flush_workqueue(rdev->wq);
|
cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
|
||||||
|
|
||||||
device_remove_file(rdev->dev, &dev_attr_power_profile);
|
device_remove_file(rdev->dev, &dev_attr_power_profile);
|
||||||
device_remove_file(rdev->dev, &dev_attr_power_method);
|
device_remove_file(rdev->dev, &dev_attr_power_method);
|
||||||
@ -690,12 +675,12 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev)
|
|||||||
radeon_pm_get_dynpm_state(rdev);
|
radeon_pm_get_dynpm_state(rdev);
|
||||||
radeon_pm_set_clocks(rdev);
|
radeon_pm_set_clocks(rdev);
|
||||||
|
|
||||||
queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
|
schedule_delayed_work(&rdev->pm.dynpm_idle_work,
|
||||||
msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
|
msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
|
||||||
} else if (rdev->pm.dynpm_state == DYNPM_STATE_PAUSED) {
|
} else if (rdev->pm.dynpm_state == DYNPM_STATE_PAUSED) {
|
||||||
rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
|
rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
|
||||||
queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
|
schedule_delayed_work(&rdev->pm.dynpm_idle_work,
|
||||||
msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
|
msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
|
||||||
DRM_DEBUG_DRIVER("radeon: dynamic power management activated\n");
|
DRM_DEBUG_DRIVER("radeon: dynamic power management activated\n");
|
||||||
}
|
}
|
||||||
} else { /* count == 0 */
|
} else { /* count == 0 */
|
||||||
@ -800,8 +785,8 @@ static void radeon_dynpm_idle_work_handler(struct work_struct *work)
|
|||||||
radeon_pm_set_clocks(rdev);
|
radeon_pm_set_clocks(rdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
|
schedule_delayed_work(&rdev->pm.dynpm_idle_work,
|
||||||
msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
|
msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
|
||||||
}
|
}
|
||||||
mutex_unlock(&rdev->pm.mutex);
|
mutex_unlock(&rdev->pm.mutex);
|
||||||
ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
|
ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
|
||||||
|
@ -692,7 +692,7 @@ int rs600_irq_process(struct radeon_device *rdev)
|
|||||||
/* reset gui idle ack. the status bit is broken */
|
/* reset gui idle ack. the status bit is broken */
|
||||||
rdev->irq.gui_idle_acked = false;
|
rdev->irq.gui_idle_acked = false;
|
||||||
if (queue_hotplug)
|
if (queue_hotplug)
|
||||||
queue_work(rdev->wq, &rdev->hotplug_work);
|
schedule_work(&rdev->hotplug_work);
|
||||||
if (rdev->msi_enabled) {
|
if (rdev->msi_enabled) {
|
||||||
switch (rdev->family) {
|
switch (rdev->family) {
|
||||||
case CHIP_RS600:
|
case CHIP_RS600:
|
||||||
|
Loading…
Reference in New Issue
Block a user