diff mbox series

hibernation:stop resume screen during hibernation

Message ID 20210622124547.28317-1-pingshuo@uniontech.com
State New
Headers show
Series hibernation:stop resume screen during hibernation | expand

Commit Message

pingshuo June 22, 2021, 12:45 p.m. UTC
The display will be woken up during hibernation.
if the computer equipment is poor, it will cause the screen to flicker.
Skip to reusme the display devices in "thaw".

Signed-off-by: pingshuo <pingshuo@uniontech.com>
---
 drivers/base/power/main.c | 43 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

Comments

Rafael J. Wysocki June 22, 2021, 1:06 p.m. UTC | #1
On Tue, Jun 22, 2021 at 2:46 PM pingshuo <pingshuo@uniontech.com> wrote:
>
> The display will be woken up during hibernation.

That actually depends on its driver.

> if the computer equipment is poor, it will cause the screen to flicker.
> Skip to reusme the display devices in "thaw".

But this patch looks like a proof of concept rather than a proper solution.

This needs to be done more carefully.

> Signed-off-by: pingshuo <pingshuo@uniontech.com>
> ---
>  drivers/base/power/main.c | 43 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 43 insertions(+)
>
> diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
> index f893c3c5af07..f3e92ac7b4b3 100644
> --- a/drivers/base/power/main.c
> +++ b/drivers/base/power/main.c
> @@ -35,11 +35,14 @@
>  #include <linux/cpuidle.h>
>  #include <linux/devfreq.h>
>  #include <linux/timer.h>
> +#include <linux/pci.h>
>
>  #include "../base.h"
>  #include "power.h"
>
>  typedef int (*pm_callback_t)(struct device *);
> +#define VIDEO_PCI_CLASS 0x030000
> +#define VIDEO_PCI_CLASS_VALID 0xff0000
>
>  #define list_for_each_entry_rcu_locked(pos, head, member) \
>         list_for_each_entry_rcu(pos, head, member, \
> @@ -693,6 +696,40 @@ static void async_resume_noirq(void *data, async_cookie_t cookie)
>         put_device(dev);
>  }
>
> +/**
> + * dpm_resume_skip_display_devices - Skip to reusme the display devices.
> + * @dev: Device to handle.
> + * @state: PM transition of the system being carried out.
> + *
> + * Delete the display devices from the wake-up list during the "thaw".
> + */
> +static int dpm_resume_skip_display_devices(struct device *dev, pm_message_t state)
> +{
> +       struct pci_dev *pci_test = to_pci_dev(dev);

If you want to deal with PCI devices, that needs to happen at the PCI
bus type level in the first place.

> +
> +       if (state.event == PM_EVENT_THAW) {
> +               /*
> +                * Filter out the display devices
> +                */
> +               if ((pci_test && ((pci_test->class & VIDEO_PCI_CLASS_VALID) == VIDEO_PCI_CLASS)) ||
> +                       (dev->driver && dev->driver->name &&
> +                       strncmp(dev->driver->name, "video", 6) == 0)) {
> +
> +                       pr_info("Skip the display devices during the thaw.");
> +                       /*
> +                        * Remove the display devices from the resume stage
> +                        */
> +                       list_del(&dev->power.entry);
> +                       /*
> +                        * Remove the display devices from the power down stage
> +                        */
> +                       list_del(&dev->kobj.entry);
> +                       return 1;
> +               }
> +       }
> +       return 0;
> +}
> +
>  static void dpm_noirq_resume_devices(pm_message_t state)
>  {
>         struct device *dev;
> @@ -713,6 +750,10 @@ static void dpm_noirq_resume_devices(pm_message_t state)
>         while (!list_empty(&dpm_noirq_list)) {
>                 dev = to_device(dpm_noirq_list.next);
>                 get_device(dev);
> +
> +               if (dpm_resume_skip_display_devices(dev, state))
> +                       continue;
> +
>                 list_move_tail(&dev->power.entry, &dpm_late_early_list);
>                 mutex_unlock(&dpm_list_mtx);
>
> @@ -737,6 +778,8 @@ static void dpm_noirq_resume_devices(pm_message_t state)
>         trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, false);
>  }
>
> +
> +
>  /**
>   * dpm_resume_noirq - Execute "noirq resume" callbacks for all devices.
>   * @state: PM transition of the system being carried out.
> --
pingshuo June 24, 2021, 2:06 a.m. UTC | #2
>> The display will be woken up during hibernation.

>

> That actually depends on its driver.

>

>> if the computer equipment is poor, it will cause the screen to flicker.

>> Skip to resume the display devices in "thaw".


> But this patch looks like a proof of concept rather than a proper solution.


>This needs to be done more carefully.


When entering hibernation, the display screen will be off first, then 
will be on (the image data is written to the disk at this time), and 
finally the display screen will be off again.

> If you want to deal with PCI devices, that needs to happen at the PCI

bus type level in the first place

what is the "PCI bus type level" mean ? Do you mean to modify it in 
dev->bus or dev-> bus -> pm?


  We tested different graphics cards,like amdgpu, radeon,i915,nvidia, 
this issue occurs during entering hibernation.
Based on the above test, several graphics cards will be resumed and the 
screen is on, so we add code here.
Did you have any idea  if these code is added in here ?




Please answer a question for me.

Resuming device is to write the image to the disk. Is it necessary to 
wake up all devices? Why not just wake up the devices related to writing 
image?

Anticipate your response.

thanks,
                                                               pingshuo
diff mbox series

Patch

diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index f893c3c5af07..f3e92ac7b4b3 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -35,11 +35,14 @@ 
 #include <linux/cpuidle.h>
 #include <linux/devfreq.h>
 #include <linux/timer.h>
+#include <linux/pci.h>
 
 #include "../base.h"
 #include "power.h"
 
 typedef int (*pm_callback_t)(struct device *);
+#define VIDEO_PCI_CLASS 0x030000
+#define VIDEO_PCI_CLASS_VALID 0xff0000
 
 #define list_for_each_entry_rcu_locked(pos, head, member) \
 	list_for_each_entry_rcu(pos, head, member, \
@@ -693,6 +696,40 @@  static void async_resume_noirq(void *data, async_cookie_t cookie)
 	put_device(dev);
 }
 
+/**
+ * dpm_resume_skip_display_devices - Skip to reusme the display devices.
+ * @dev: Device to handle.
+ * @state: PM transition of the system being carried out.
+ *
+ * Delete the display devices from the wake-up list during the "thaw".
+ */
+static int dpm_resume_skip_display_devices(struct device *dev, pm_message_t state)
+{
+	struct pci_dev *pci_test = to_pci_dev(dev);
+
+	if (state.event == PM_EVENT_THAW) {
+		/*
+		 * Filter out the display devices
+		 */
+		if ((pci_test && ((pci_test->class & VIDEO_PCI_CLASS_VALID) == VIDEO_PCI_CLASS)) ||
+			(dev->driver && dev->driver->name &&
+			strncmp(dev->driver->name, "video", 6) == 0)) {
+
+			pr_info("Skip the display devices during the thaw.");
+			/*
+			 * Remove the display devices from the resume stage
+			 */
+			list_del(&dev->power.entry);
+			/*
+			 * Remove the display devices from the power down stage
+			 */
+			list_del(&dev->kobj.entry);
+			return 1;
+		}
+	}
+	return 0;
+}
+
 static void dpm_noirq_resume_devices(pm_message_t state)
 {
 	struct device *dev;
@@ -713,6 +750,10 @@  static void dpm_noirq_resume_devices(pm_message_t state)
 	while (!list_empty(&dpm_noirq_list)) {
 		dev = to_device(dpm_noirq_list.next);
 		get_device(dev);
+
+		if (dpm_resume_skip_display_devices(dev, state))
+			continue;
+
 		list_move_tail(&dev->power.entry, &dpm_late_early_list);
 		mutex_unlock(&dpm_list_mtx);
 
@@ -737,6 +778,8 @@  static void dpm_noirq_resume_devices(pm_message_t state)
 	trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, false);
 }
 
+
+
 /**
  * dpm_resume_noirq - Execute "noirq resume" callbacks for all devices.
  * @state: PM transition of the system being carried out.