Browse Source

Add HandleNvidiaSleep option to logind.conf (#140)

Although elogind can now handle /proc/driver/nvidia/suspend, its
interface is considered experimental, and should not be writen to by
elogind unless it is really needed.

The new option therefore defaults to "no", and thus lets users opt-in
to elogind taking care of writing suspend/hibernate/resume to that
interface.

See more information at:
https://download.nvidia.com/XFree86/Linux-x86_64/455.38/README/powermanagement.html

Bug: #140

Signed-off-by: Sven Eden <sven.eden@prydeworx.com>
debian
Sven Eden 1 year ago
parent
commit
4be6a26164
  1. 2
      Makefile
  2. 38
      man/logind.conf.xml
  3. 3
      src/login/elogind.c
  4. 1
      src/login/logind-gperf.gperf
  5. 1
      src/login/logind.conf.in
  6. 3
      src/login/logind.h
  7. 1
      src/shared/sleep-config.c
  8. 21
      src/sleep/sleep.c

2
Makefile

@ -95,7 +95,7 @@ install: build
+@(echo "make[2]: Leaving directory '$(BUILDDIR)'")
justprint: $(CONFIG)
+($(MAKE) all JUST_PRINT=YES)
+(BUILDDIR=$(HERE)/build $(MAKE) all JUST_PRINT=YES)
loginctl: $(CONFIG)
+@(echo "make[2]: Entering directory '$(BUILDDIR)'")

38
man/logind.conf.xml

@ -531,7 +531,7 @@
When this happens, <command>elogind</command> will broadcast the cancellation, unless
<varname>BroadcastPowerOffInterrupts</varname> is set to <literal>no</literal>.
See <citerefentry><refentrytitle>loginctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> for more
information about hook directories.</para></listitem>
information about hook directories.</para></listitem>
</varlistentry>
<varlistentry>
@ -539,16 +539,38 @@
<term><varname>BroadcastSuspendInterrupts=</varname></term>
<listitem><para>When suspend/hibernate actions are allowed to be interrupted by setting
<varname>AllowSuspendInterrupts</varname> to <literal>yes</literal>, <command>elogind</command> will, if
any of the execute in <option>[/usr]/lib[64]/elogind/system-sleep/</option> or
<option>/etc/elogind/system-sleep/</option> fails, interrupt and cancel the suspend action.
When this happens, <command>elogind</command> will broadcast the cancellation, unless
<varname>BroadcastSuspendInterrupts</varname> is set to <literal>no</literal>.
See <citerefentry><refentrytitle>loginctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> for more
information about hook directories.</para></listitem>
<varname>AllowSuspendInterrupts</varname> to <literal>yes</literal>, <command>elogind</command> will, if
any of the execute in <option>[/usr]/lib[64]/elogind/system-sleep/</option> or
<option>/etc/elogind/system-sleep/</option> fails, interrupt and cancel the suspend action.
When this happens, <command>elogind</command> will broadcast the cancellation, unless
<varname>BroadcastSuspendInterrupts</varname> is set to <literal>no</literal>.
See <citerefentry><refentrytitle>loginctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> for more
information about hook directories.</para></listitem>
</varlistentry>
</variablelist>
<variablelist>
<para>Optional hardware control:</para>
<varlistentry>
<term><varname>HandleNvidiaSleep=</varname></term>
<listitem><para>If the file <filename>/proc/driver/nvidia/suspend</filename> exists, elogind will write either
<literal>suspend</literal> when suspending, or <literal>hibernate</literal> when one of the other
power-saving modes is entered, to it. Additionally elogind will try to switch the current VT to 63 before
putting the Nvidia card to sleep.
After resuming from suspend/hibernate, elogind will write <literal>resume</literal> to the Nvidia
<filename>suspend</filename> file, and switches the VT back to where it was before suspending the card.
</para>
<para>Using the <filename>/proc/driver/nvidia/suspend</filename> is considered experimental by Nvidia, and
should only be used if it is neccessary, and the official <filename>/usr/bin/nvidia-sleep.sh</filename>
can not be used from a system-sleep hook script for some reason.
Please read the
<ulink url="https://download.nvidia.com/XFree86/Linux-x86_64/455.38/README/powermanagement.html">Nvidia
power management guide</ulink> for more information</para></listitem>
</varlistentry>
</variablelist>
</refsect2>
<!-- // 1 -->
</refsect1>

3
src/login/elogind.c

@ -400,6 +400,9 @@ int elogind_manager_new( Manager* m ) {
m->callback_failed = false;
m->callback_must_succeed = false;
/* allow manipulating Nvidia cards */
m->handle_nvidia_sleep = false;
/* Init sleep modes and states */
m->suspend_modes = NULL;
m->suspend_states = NULL;

1
src/login/logind-gperf.gperf

@ -26,6 +26,7 @@ Sleep.AllowPowerOffInterrupts, config_parse_bool, 0, offsetof(Manag
Sleep.BroadcastPowerOffInterrupts, config_parse_bool, 0, offsetof(Manager, broadcast_poweroff_interrupts)
Sleep.AllowSuspendInterrupts, config_parse_bool, 0, offsetof(Manager, allow_suspend_interrupts)
Sleep.BroadcastSuspendInterrupts, config_parse_bool, 0, offsetof(Manager, broadcast_suspend_interrupts)
Sleep.HandleNvidiaSleep, config_parse_bool, 0, offsetof(Manager, handle_nvidia_sleep)
Sleep.SuspendMode, config_parse_strv, 0, offsetof(Manager, suspend_modes)
Sleep.SuspendState, config_parse_strv, 0, offsetof(Manager, suspend_states)
Sleep.HibernateMode, config_parse_strv, 0, offsetof(Manager, hibernate_modes)

1
src/login/logind.conf.in

@ -44,6 +44,7 @@
#BroadcastPowerOffInterrupts=yes
#AllowSuspendInterrupts=no
#BroadcastSuspendInterrupts=yes
#HandleNvidiaSleep=no
#SuspendState=mem standby freeze
#SuspendMode=
#HibernateState=disk

3
src/login/logind.h

@ -135,6 +135,9 @@ struct Manager {
bool broadcast_poweroff_interrupts, broadcast_suspend_interrupts;
bool callback_failed, callback_must_succeed;
/* Allow elogind to put Nvidia cards to sleep */
bool handle_nvidia_sleep;
/* If a shutdown/suspend was delayed due to a inhibitor this
contains the action we are supposed to perform after the
delay is over */

1
src/shared/sleep-config.c

@ -67,6 +67,7 @@ int parse_sleep_config(SleepConfig **ret_sleep_config) {
{ "Sleep", "BroadcastPowerOffInterrupts", config_parse_bool, 0, &sc->broadcast_poweroff_interrupts },
{ "Sleep", "AllowSuspendInterrupts", config_parse_bool, 0, &sc->allow_suspend_interrupts },
{ "Sleep", "BroadcastSuspendInterrupts", config_parse_bool, 0, &sc->broadcast_suspend_interrupts },
{ "Sleep", "HandleNvidiaSleep", config_parse_bool, 0, &sc->handle_nvidia_sleep },
#endif // 1
{}
};

21
src/sleep/sleep.c

@ -397,7 +397,7 @@ static int execute(Manager* m, char const* verb, char **modes, char **states) {
[STDOUT_COLLECT] = m,
[STDOUT_CONSUME] = m,
};
int have_nvidia;
int have_nvidia = 0;
unsigned vtnr = 0;
int e;
_cleanup_free_ char *l = NULL;
@ -468,25 +468,18 @@ static int execute(Manager* m, char const* verb, char **modes, char **states) {
return -ECANCELED;
}
log_struct(LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR,
LOG_MESSAGE("Suspending system..."),
"SLEEP=%s", verb);
log_struct(LOG_INFO, "MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR, LOG_MESSAGE("Suspending system..."), "SLEEP=%s", verb);
/* See whether we have an nvidia card to put to sleep */
have_nvidia = nvidia_sleep(m, verb, &vtnr);
if ( m->handle_nvidia_sleep )
have_nvidia = nvidia_sleep(m, verb, &vtnr);
r = write_state(&f, states);
if (r < 0)
log_struct_errno(LOG_ERR, r,
"MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR,
LOG_MESSAGE("Failed to suspend system. System resumed again: %m"),
"SLEEP=%s", verb);
log_struct_errno(LOG_ERR, r, "MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR,
LOG_MESSAGE("Failed to suspend system. System resumed again: %m"), "SLEEP=%s", verb);
else
log_struct(LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR,
LOG_MESSAGE("System resumed."),
"SLEEP=%s", verb);
log_struct(LOG_INFO, "MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR, LOG_MESSAGE("System resumed."), "SLEEP=%s", verb);
/* Wakeup a possibly put to sleep nvidia card */
if (have_nvidia)

Loading…
Cancel
Save