From: Stefan Demharter <stefan.demharter@gmx.net>
To: Jani Nikula <jani.nikula@linux.intel.com>,
Alex Deucher <alexdeucher@gmail.com>,
Dave Airlie <airlied@gmail.com>
Cc: Maling list - DRI developers <dri-devel@lists.freedesktop.org>
Subject: Re: [PATCH RFC v2] vga_switcheroo: restore mux and power states upon resume from hibernation.
Date: Sat, 27 Sep 2014 00:32:16 +0200 [thread overview]
Message-ID: <5425E970.8@gmx.net> (raw)
In-Reply-To: <87ha0me26h.fsf@intel.com>
On 2014-09-05 13:28, Jani Nikula wrote:
> On Fri, 31 Jan 2014, Alex Deucher <alexdeucher@gmail.com> wrote:
>> On Thu, Jan 30, 2014 at 6:46 PM, Stefan Demharter
>> <stefan.demharter@gmx.net> wrote:
>>> Saves the current state of the mux and restores it upon resume from hibernation.
>>> This is needed for muxed systems because the state of the mux doesn't survive a
>>> hibernation-resume cycle. Furthermore also restores the power state of a GPU
>>> to OFF after resume from hibernation if it was OFF before hibernation.
>>>
>>> Signed-off-by: Stefan Demharter <stefan.demharter@gmx.net>
>>
>> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
>
> Despite the review, looks like this one has fallen between the
> cracks. There's some comments from Chris at [1].
>
> Dave?
>
>
> BR,
> Jani.
>
> [1] https://bugs.freedesktop.org/show_bug.cgi?id=70863#c4
sorry for the late response.
But here are my thoughts/answers to the points mentioned by Chris:
1. I will provide an updated patch which has the description in the changelog very soon.
2. I just want to set the gpu state to the power state the system thinks the gpu is in,
so I don't think this is necessary and may also have other side effects.
3./4. As the mux is actually always in a valid state I've removed the
undefined state in the updated patch.
It is assumed that the mux is initially set to MIGD.
The logic should also work with mux-less systems.
For details please look into the updated patch.
Regards,
Stefan
>
>>
>>> ---
>>> drivers/gpu/vga/vga_switcheroo.c | 96 +++++++++++++++++++++++++++++++++++-----
>>> 1 file changed, 85 insertions(+), 11 deletions(-)
>>>
>>> diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
>>> index ec0ae2d..85f41b9 100644
>>> --- a/drivers/gpu/vga/vga_switcheroo.c
>>> +++ b/drivers/gpu/vga/vga_switcheroo.c
>>> @@ -28,6 +28,7 @@
>>> #include <linux/console.h>
>>> #include <linux/vga_switcheroo.h>
>>> #include <linux/pm_runtime.h>
>>> +#include <linux/suspend.h>
>>>
>>> #include <linux/vgaarb.h>
>>>
>>> @@ -72,6 +73,64 @@ static struct vgasr_priv vgasr_priv = {
>>> .clients = LIST_HEAD_INIT(vgasr_priv.clients),
>>> };
>>>
>>> +#define MUX_STATE_UNDEFINED (-1)
>>> +/*
>>> + * The next variable stores the state of the mux
>>> + * so it can be restored upon resume from hibernation.
>>> + */
>>> +static int mux_state = MUX_STATE_UNDEFINED;
>>> +
>>> +static void vga_restore_mux(void)
>>> +{
>>> + if (mux_state != MUX_STATE_UNDEFINED) {
>>> + int ret;
>>> + pr_info("vga_switcheroo: restoring mux state to %s\n",
>>> + mux_state == VGA_SWITCHEROO_IGD ? "IGD" : "DIS");
>>> +
>>> + ret = vgasr_priv.handler->switchto(mux_state);
>>> + if (ret)
>>> + pr_warn("vga_switcheroo: mux switch failed (%d)\n", ret);
>>> + }
>>> +}
>>> +
>>> +static void vga_restore_power_state(void)
>>> +{
>>> + struct vga_switcheroo_client *client;
>>> +
>>> + if (!vgasr_priv.handler->power_state)
>>> + return;
>>> +
>>> + list_for_each_entry(client, &vgasr_priv.clients, list) {
>>> + if (client_is_vga(client) && client->pwr_state == VGA_SWITCHEROO_OFF) {
>>> + pr_info("vga_switcheroo: setting power state of %s to OFF\n",
>>> + client->id == VGA_SWITCHEROO_IGD ? "IGD" : "DIS");
>>> + vgasr_priv.handler->power_state(client->id, client->pwr_state);
>>> + }
>>> + }
>>> +}
>>> +
>>> +/*
>>> + * Handle resume from hibernation:
>>> + * Restore mux state and power states for switcheroo controlled GPUs.
>>> + */
>>> +static int vga_resume(struct notifier_block *nb, unsigned long action, void *unused)
>>> +{
>>> + switch (action) {
>>> + case PM_POST_HIBERNATION:
>>> + mutex_lock(&vgasr_mutex);
>>> + vga_restore_mux();
>>> + vga_restore_power_state();
>>> + mutex_unlock(&vgasr_mutex);
>>> + break;
>>> + }
>>> + return 0;
>>> +}
>>> +
>>> +static struct notifier_block vga_switcheroo_pm_nb = {
>>> + .notifier_call = vga_resume,
>>> + .priority = 0,
>>> +};
>>> +
>>> static bool vga_switcheroo_ready(void)
>>> {
>>> /* we're ready if we get two clients + handler */
>>> @@ -84,6 +143,8 @@ static void vga_switcheroo_enable(void)
>>> int ret;
>>> struct vga_switcheroo_client *client;
>>>
>>> + pr_info("vga_switcheroo: enabled\n");
>>> +
>>> /* call the handler to init */
>>> if (vgasr_priv.handler->init)
>>> vgasr_priv.handler->init();
>>> @@ -99,6 +160,15 @@ static void vga_switcheroo_enable(void)
>>> }
>>> vga_switcheroo_debugfs_init(&vgasr_priv);
>>> vgasr_priv.active = true;
>>> + register_pm_notifier(&vga_switcheroo_pm_nb);
>>> +}
>>> +
>>> +void vga_switcheroo_disable(void)
>>> +{
>>> + unregister_pm_notifier(&vga_switcheroo_pm_nb);
>>> + vgasr_priv.active = false;
>>> + vga_switcheroo_debugfs_fini(&vgasr_priv);
>>> + pr_info("vga_switcheroo: disabled\n");
>>> }
>>>
>>> int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler)
>>> @@ -111,7 +181,6 @@ int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler)
>>>
>>> vgasr_priv.handler = handler;
>>> if (vga_switcheroo_ready()) {
>>> - printk(KERN_INFO "vga_switcheroo: enabled\n");
>>> vga_switcheroo_enable();
>>> }
>>> mutex_unlock(&vgasr_mutex);
>>> @@ -124,9 +193,7 @@ void vga_switcheroo_unregister_handler(void)
>>> mutex_lock(&vgasr_mutex);
>>> vgasr_priv.handler = NULL;
>>> if (vgasr_priv.active) {
>>> - pr_info("vga_switcheroo: disabled\n");
>>> - vga_switcheroo_debugfs_fini(&vgasr_priv);
>>> - vgasr_priv.active = false;
>>> + vga_switcheroo_disable();
>>> }
>>> mutex_unlock(&vgasr_mutex);
>>> }
>>> @@ -155,7 +222,6 @@ static int register_client(struct pci_dev *pdev,
>>> vgasr_priv.registered_clients++;
>>>
>>> if (vga_switcheroo_ready()) {
>>> - printk(KERN_INFO "vga_switcheroo: enabled\n");
>>> vga_switcheroo_enable();
>>> }
>>> mutex_unlock(&vgasr_mutex);
>>> @@ -235,9 +301,7 @@ void vga_switcheroo_unregister_client(struct pci_dev *pdev)
>>> kfree(client);
>>> }
>>> if (vgasr_priv.active && vgasr_priv.registered_clients < 2) {
>>> - printk(KERN_INFO "vga_switcheroo: disabled\n");
>>> - vga_switcheroo_debugfs_fini(&vgasr_priv);
>>> - vgasr_priv.active = false;
>>> + vga_switcheroo_disable();
>>> }
>>> mutex_unlock(&vgasr_mutex);
>>> }
>>> @@ -262,10 +326,11 @@ static int vga_switcheroo_show(struct seq_file *m, void *v)
>>> int i = 0;
>>> mutex_lock(&vgasr_mutex);
>>> list_for_each_entry(client, &vgasr_priv.clients, list) {
>>> - seq_printf(m, "%d:%s%s:%c:%s%s:%s\n", i,
>>> + seq_printf(m, "%d:%s%s:%c%s:%s%s:%s\n", i,
>>> client_id(client) == VGA_SWITCHEROO_DIS ? "DIS" : "IGD",
>>> client_is_vga(client) ? "" : "-Audio",
>>> client->active ? '+' : ' ',
>>> + client_id(client) == mux_state ? "mux" : "",
>>> client->driver_power_control ? "Dyn" : "",
>>> client->pwr_state ? "Pwr" : "Off",
>>> pci_name(client->pdev));
>>> @@ -304,6 +369,15 @@ static int vga_switchoff(struct vga_switcheroo_client *client)
>>> return 0;
>>> }
>>>
>>> +static int vga_switchto(int client_id)
>>> +{
>>> + int ret = vgasr_priv.handler->switchto(client_id);
>>> +
>>> + if (ret == 0)
>>> + mux_state = client_id;
>>> + return ret;
>>> +}
>>> +
>>> static void set_audio_state(int id, int state)
>>> {
>>> struct vga_switcheroo_client *client;
>>> @@ -353,7 +427,7 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
>>> console_unlock();
>>> }
>>>
>>> - ret = vgasr_priv.handler->switchto(new_client->id);
>>> + ret = vga_switchto(new_client->id);
>>> if (ret)
>>> return ret;
>>>
>>> @@ -468,7 +542,7 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
>>> vgasr_priv.delayed_switch_active = false;
>>>
>>> if (just_mux) {
>>> - ret = vgasr_priv.handler->switchto(client_id);
>>> + ret = vga_switchto(client_id);
>>> goto out;
>>> }
>>>
>>> --
>>> 1.8.5.3
>>>
>>> _______________________________________________
>>> dri-devel mailing list
>>> dri-devel@lists.freedesktop.org
>>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>
prev parent reply other threads:[~2014-09-26 22:32 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-30 23:46 [PATCH RFC v2] vga_switcheroo: restore mux and power states upon resume from hibernation Stefan Demharter
2014-01-31 14:32 ` Alex Deucher
2014-09-05 11:28 ` Jani Nikula
2014-09-26 22:32 ` Stefan Demharter [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5425E970.8@gmx.net \
--to=stefan.demharter@gmx.net \
--cc=airlied@gmail.com \
--cc=alexdeucher@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=jani.nikula@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.