mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-04 17:44:14 +08:00
vga_switcheroo: Add missing locking
The following functions iterate over the client list, invoke client callbacks or invoke handler callbacks without locking anything at all: - Introduced byc8e9cf7bb2
("vga_switcheroo: Add a helper function to get the client state"): vga_switcheroo_get_client_state() - Introduced by0d69704ae3
("gpu/vga_switcheroo: add driver control power feature. (v3)"): vga_switcheroo_set_dynamic_switch() vga_switcheroo_runtime_suspend() vga_switcheroo_runtime_resume() vga_switcheroo_runtime_resume_hdmi_audio() Refactor vga_switcheroo_runtime_resume_hdmi_audio() a bit to be able to release vgasr_mutex immediately after iterating over the client list. Signed-off-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
945ef5bb14
commit
8f12a3118f
@ -347,13 +347,18 @@ find_active_client(struct list_head *head)
|
|||||||
int vga_switcheroo_get_client_state(struct pci_dev *pdev)
|
int vga_switcheroo_get_client_state(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
struct vga_switcheroo_client *client;
|
struct vga_switcheroo_client *client;
|
||||||
|
enum vga_switcheroo_state ret;
|
||||||
|
|
||||||
|
mutex_lock(&vgasr_mutex);
|
||||||
client = find_client_from_pci(&vgasr_priv.clients, pdev);
|
client = find_client_from_pci(&vgasr_priv.clients, pdev);
|
||||||
if (!client)
|
if (!client)
|
||||||
return VGA_SWITCHEROO_NOT_FOUND;
|
ret = VGA_SWITCHEROO_NOT_FOUND;
|
||||||
if (!vgasr_priv.active)
|
else if (!vgasr_priv.active)
|
||||||
return VGA_SWITCHEROO_INIT;
|
ret = VGA_SWITCHEROO_INIT;
|
||||||
return client->pwr_state;
|
else
|
||||||
|
ret = client->pwr_state;
|
||||||
|
mutex_unlock(&vgasr_mutex);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(vga_switcheroo_get_client_state);
|
EXPORT_SYMBOL(vga_switcheroo_get_client_state);
|
||||||
|
|
||||||
@ -845,15 +850,16 @@ void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev,
|
|||||||
{
|
{
|
||||||
struct vga_switcheroo_client *client;
|
struct vga_switcheroo_client *client;
|
||||||
|
|
||||||
|
mutex_lock(&vgasr_mutex);
|
||||||
client = find_client_from_pci(&vgasr_priv.clients, pdev);
|
client = find_client_from_pci(&vgasr_priv.clients, pdev);
|
||||||
if (!client)
|
if (!client || !client->driver_power_control) {
|
||||||
return;
|
mutex_unlock(&vgasr_mutex);
|
||||||
|
|
||||||
if (!client->driver_power_control)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
client->pwr_state = dynamic;
|
client->pwr_state = dynamic;
|
||||||
set_audio_state(client->id, dynamic);
|
set_audio_state(client->id, dynamic);
|
||||||
|
mutex_unlock(&vgasr_mutex);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(vga_switcheroo_set_dynamic_switch);
|
EXPORT_SYMBOL(vga_switcheroo_set_dynamic_switch);
|
||||||
|
|
||||||
@ -866,9 +872,11 @@ static int vga_switcheroo_runtime_suspend(struct device *dev)
|
|||||||
ret = dev->bus->pm->runtime_suspend(dev);
|
ret = dev->bus->pm->runtime_suspend(dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
mutex_lock(&vgasr_mutex);
|
||||||
if (vgasr_priv.handler->switchto)
|
if (vgasr_priv.handler->switchto)
|
||||||
vgasr_priv.handler->switchto(VGA_SWITCHEROO_IGD);
|
vgasr_priv.handler->switchto(VGA_SWITCHEROO_IGD);
|
||||||
vga_switcheroo_power_switch(pdev, VGA_SWITCHEROO_OFF);
|
vga_switcheroo_power_switch(pdev, VGA_SWITCHEROO_OFF);
|
||||||
|
mutex_unlock(&vgasr_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -877,7 +885,9 @@ static int vga_switcheroo_runtime_resume(struct device *dev)
|
|||||||
struct pci_dev *pdev = to_pci_dev(dev);
|
struct pci_dev *pdev = to_pci_dev(dev);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(&vgasr_mutex);
|
||||||
vga_switcheroo_power_switch(pdev, VGA_SWITCHEROO_ON);
|
vga_switcheroo_power_switch(pdev, VGA_SWITCHEROO_ON);
|
||||||
|
mutex_unlock(&vgasr_mutex);
|
||||||
ret = dev->bus->pm->runtime_resume(dev);
|
ret = dev->bus->pm->runtime_resume(dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@ -923,29 +933,33 @@ EXPORT_SYMBOL(vga_switcheroo_fini_domain_pm_ops);
|
|||||||
static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev)
|
static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = to_pci_dev(dev);
|
struct pci_dev *pdev = to_pci_dev(dev);
|
||||||
|
struct vga_switcheroo_client *client;
|
||||||
|
struct device *video_dev = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
struct vga_switcheroo_client *client, *found = NULL;
|
|
||||||
|
|
||||||
/* we need to check if we have to switch back on the video
|
/* we need to check if we have to switch back on the video
|
||||||
device so the audio device can come back */
|
device so the audio device can come back */
|
||||||
|
mutex_lock(&vgasr_mutex);
|
||||||
list_for_each_entry(client, &vgasr_priv.clients, list) {
|
list_for_each_entry(client, &vgasr_priv.clients, list) {
|
||||||
if (PCI_SLOT(client->pdev->devfn) == PCI_SLOT(pdev->devfn) &&
|
if (PCI_SLOT(client->pdev->devfn) == PCI_SLOT(pdev->devfn) &&
|
||||||
client_is_vga(client)) {
|
client_is_vga(client)) {
|
||||||
found = client;
|
video_dev = &client->pdev->dev;
|
||||||
ret = pm_runtime_get_sync(&client->pdev->dev);
|
|
||||||
if (ret) {
|
|
||||||
if (ret != 1)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&vgasr_mutex);
|
||||||
|
|
||||||
|
if (video_dev) {
|
||||||
|
ret = pm_runtime_get_sync(video_dev);
|
||||||
|
if (ret && ret != 1)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
ret = dev->bus->pm->runtime_resume(dev);
|
ret = dev->bus->pm->runtime_resume(dev);
|
||||||
|
|
||||||
/* put the reference for the gpu */
|
/* put the reference for the gpu */
|
||||||
if (found) {
|
if (video_dev) {
|
||||||
pm_runtime_mark_last_busy(&found->pdev->dev);
|
pm_runtime_mark_last_busy(video_dev);
|
||||||
pm_runtime_put_autosuspend(&found->pdev->dev);
|
pm_runtime_put_autosuspend(video_dev);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user