€•’TŒsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”(hhŒparent”hubaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ0/translations/zh_CN/power/suspend-and-interrupts”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”(hhhh2ubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/zh_TW/power/suspend-and-interrupts”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”(hhhhFubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/it_IT/power/suspend-and-interrupts”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”(hhhhZubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/ja_JP/power/suspend-and-interrupts”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”(hhhhnubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/ko_KR/power/suspend-and-interrupts”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”(hhhh‚ubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/sp_SP/power/suspend-and-interrupts”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒ$System Suspend and Device Interrupts”h]”hŒ$System Suspend and Device Interrupts”…””}”(hhªhh¨hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hh£hžhhŸŒJ/var/lib/git/docbuild/linux/Documentation/power/suspend-and-interrupts.rst”h KubhŒ paragraph”“”)”}”(hŒUCopyright (C) 2014 Intel Corp. Author: Rafael J. Wysocki ”h]”(hŒ:Copyright (C) 2014 Intel Corp. Author: Rafael J. Wysocki <”…””}”(hŒ:Copyright (C) 2014 Intel Corp. Author: Rafael J. Wysocki <”hh¹hžhhŸNh NubhŒ reference”“”)”}”(hŒrafael.j.wysocki@intel.com”h]”hŒrafael.j.wysocki@intel.com”…””}”(hhhhÄhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”Œ!mailto:rafael.j.wysocki@intel.com”uh1hÂhh¹ubhŒ>”…””}”(hŒ>”hh¹hžhhŸNh Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Khh£hžhubh¢)”}”(hhh]”(h§)”}”(hŒ#Suspending and Resuming Device IRQs”h]”hŒ#Suspending and Resuming Device IRQs”…””}”(hhähhâhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hhßhžhhŸh¶h K ubh¸)”}”(hXDevice interrupt request lines (IRQs) are generally disabled during system suspend after the "late" phase of suspending devices (that is, after all of the ->prepare, ->suspend and ->suspend_late callbacks have been executed for all devices). That is done by suspend_device_irqs().”h]”hXDevice interrupt request lines (IRQs) are generally disabled during system suspend after the “late†phase of suspending devices (that is, after all of the ->prepare, ->suspend and ->suspend_late callbacks have been executed for all devices). That is done by suspend_device_irqs().”…””}”(hhòhhðhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K hhßhžhubh¸)”}”(hX>The rationale for doing so is that after the "late" phase of device suspend there is no legitimate reason why any interrupts from suspended devices should trigger and if any devices have not been suspended properly yet, it is better to block interrupts from them anyway. Also, in the past we had problems with interrupt handlers for shared IRQs that device drivers implementing them were not prepared for interrupts triggering after their devices had been suspended. In some cases they would attempt to access, for example, memory address spaces of suspended devices and cause unpredictable behavior to ensue as a result. Unfortunately, such problems are very difficult to debug and the introduction of suspend_device_irqs(), along with the "noirq" phase of device suspend and resume, was the only practical way to mitigate them.”h]”hXFThe rationale for doing so is that after the “late†phase of device suspend there is no legitimate reason why any interrupts from suspended devices should trigger and if any devices have not been suspended properly yet, it is better to block interrupts from them anyway. Also, in the past we had problems with interrupt handlers for shared IRQs that device drivers implementing them were not prepared for interrupts triggering after their devices had been suspended. In some cases they would attempt to access, for example, memory address spaces of suspended devices and cause unpredictable behavior to ensue as a result. Unfortunately, such problems are very difficult to debug and the introduction of suspend_device_irqs(), along with the “noirq†phase of device suspend and resume, was the only practical way to mitigate them.”…””}”(hjhhþhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Khhßhžhubh¸)”}”(hŒáDevice IRQs are re-enabled during system resume, right before the "early" phase of resuming devices (that is, before starting to execute ->resume_early callbacks for devices). The function doing that is resume_device_irqs().”h]”hŒåDevice IRQs are re-enabled during system resume, right before the “early†phase of resuming devices (that is, before starting to execute ->resume_early callbacks for devices). The function doing that is resume_device_irqs().”…””}”(hjhj hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Khhßhžhubeh}”(h]”Œ#suspending-and-resuming-device-irqs”ah ]”h"]”Œ#suspending and resuming device irqs”ah$]”h&]”uh1h¡hh£hžhhŸh¶h K ubh¢)”}”(hhh]”(h§)”}”(hŒThe IRQF_NO_SUSPEND Flag”h]”hŒThe IRQF_NO_SUSPEND Flag”…””}”(hj'hj%hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hj"hžhhŸh¶h K#ubh¸)”}”(hXnThere are interrupts that can legitimately trigger during the entire system suspend-resume cycle, including the "noirq" phases of suspending and resuming devices as well as during the time when nonboot CPUs are taken offline and brought back online. That applies to timer interrupts in the first place, but also to IPIs and to some other special-purpose interrupts.”h]”hXrThere are interrupts that can legitimately trigger during the entire system suspend-resume cycle, including the “noirq†phases of suspending and resuming devices as well as during the time when nonboot CPUs are taken offline and brought back online. That applies to timer interrupts in the first place, but also to IPIs and to some other special-purpose interrupts.”…””}”(hj5hj3hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K%hj"hžhubh¸)”}”(hXŸThe IRQF_NO_SUSPEND flag is used to indicate that to the IRQ subsystem when requesting a special-purpose interrupt. It causes suspend_device_irqs() to leave the corresponding IRQ enabled so as to allow the interrupt to work as expected during the suspend-resume cycle, but does not guarantee that the interrupt will wake the system from a suspended state -- for such cases it is necessary to use enable_irq_wake().”h]”hXŸThe IRQF_NO_SUSPEND flag is used to indicate that to the IRQ subsystem when requesting a special-purpose interrupt. It causes suspend_device_irqs() to leave the corresponding IRQ enabled so as to allow the interrupt to work as expected during the suspend-resume cycle, but does not guarantee that the interrupt will wake the system from a suspended state -- for such cases it is necessary to use enable_irq_wake().”…””}”(hjChjAhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K+hj"hžhubh¸)”}”(hX¢Note that the IRQF_NO_SUSPEND flag affects the entire IRQ and not just one user of it. Thus, if the IRQ is shared, all of the interrupt handlers installed for it will be executed as usual after suspend_device_irqs(), even if the IRQF_NO_SUSPEND flag was not passed to request_irq() (or equivalent) by some of the IRQ's users. For this reason, using IRQF_NO_SUSPEND and IRQF_SHARED at the same time should be avoided.”h]”hX¤Note that the IRQF_NO_SUSPEND flag affects the entire IRQ and not just one user of it. Thus, if the IRQ is shared, all of the interrupt handlers installed for it will be executed as usual after suspend_device_irqs(), even if the IRQF_NO_SUSPEND flag was not passed to request_irq() (or equivalent) by some of the IRQ’s users. For this reason, using IRQF_NO_SUSPEND and IRQF_SHARED at the same time should be avoided.”…””}”(hjQhjOhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K2hj"hžhubeh}”(h]”Œthe-irqf-no-suspend-flag”ah ]”h"]”Œthe irqf_no_suspend flag”ah$]”h&]”uh1h¡hh£hžhhŸh¶h K#ubh¢)”}”(hhh]”(h§)”}”(hŒBSystem Wakeup Interrupts, enable_irq_wake() and disable_irq_wake()”h]”hŒBSystem Wakeup Interrupts, enable_irq_wake() and disable_irq_wake()”…””}”(hjjhjhhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjehžhhŸh¶h K;ubh¸)”}”(hŒÃSystem wakeup interrupts generally need to be configured to wake up the system from sleep states, especially if they are used for different purposes (e.g. as I/O interrupts) in the working state.”h]”hŒÃSystem wakeup interrupts generally need to be configured to wake up the system from sleep states, especially if they are used for different purposes (e.g. as I/O interrupts) in the working state.”…””}”(hjxhjvhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K=hjehžhubh¸)”}”(hXµThat may involve turning on a special signal handling logic within the platform (such as an SoC) so that signals from a given line are routed in a different way during system sleep so as to trigger a system wakeup when needed. For example, the platform may include a dedicated interrupt controller used specifically for handling system wakeup events. Then, if a given interrupt line is supposed to wake up the system from sleep states, the corresponding input of that interrupt controller needs to be enabled to receive signals from the line in question. After wakeup, it generally is better to disable that input to prevent the dedicated controller from triggering interrupts unnecessarily.”h]”hXµThat may involve turning on a special signal handling logic within the platform (such as an SoC) so that signals from a given line are routed in a different way during system sleep so as to trigger a system wakeup when needed. For example, the platform may include a dedicated interrupt controller used specifically for handling system wakeup events. Then, if a given interrupt line is supposed to wake up the system from sleep states, the corresponding input of that interrupt controller needs to be enabled to receive signals from the line in question. After wakeup, it generally is better to disable that input to prevent the dedicated controller from triggering interrupts unnecessarily.”…””}”(hj†hj„hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KAhjehžhubh¸)”}”(hXThe IRQ subsystem provides two helper functions to be used by device drivers for those purposes. Namely, enable_irq_wake() turns on the platform's logic for handling the given IRQ as a system wakeup interrupt line and disable_irq_wake() turns that logic off.”h]”hXThe IRQ subsystem provides two helper functions to be used by device drivers for those purposes. Namely, enable_irq_wake() turns on the platform’s logic for handling the given IRQ as a system wakeup interrupt line and disable_irq_wake() turns that logic off.”…””}”(hj”hj’hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KKhjehžhubh¸)”}”(hXCalling enable_irq_wake() causes suspend_device_irqs() to treat the given IRQ in a special way. Namely, the IRQ remains enabled, but on the first interrupt it will be disabled, marked as pending and "suspended" so that it will be re-enabled by resume_device_irqs() during the subsequent system resume. Also the PM core is notified about the event which causes the system suspend in progress to be aborted (that doesn't have to happen immediately, but at one of the points where the suspend thread looks for pending wakeup events).”h]”hXCalling enable_irq_wake() causes suspend_device_irqs() to treat the given IRQ in a special way. Namely, the IRQ remains enabled, but on the first interrupt it will be disabled, marked as pending and “suspended†so that it will be re-enabled by resume_device_irqs() during the subsequent system resume. Also the PM core is notified about the event which causes the system suspend in progress to be aborted (that doesn’t have to happen immediately, but at one of the points where the suspend thread looks for pending wakeup events).”…””}”(hj¢hj hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KPhjehžhubh¸)”}”(hX This way every interrupt from a wakeup interrupt source will either cause the system suspend currently in progress to be aborted or wake up the system if already suspended. However, after suspend_device_irqs() interrupt handlers are not executed for system wakeup IRQs. They are only executed for IRQF_NO_SUSPEND IRQs at that time, but those IRQs should not be configured for system wakeup using enable_irq_wake().”h]”hX This way every interrupt from a wakeup interrupt source will either cause the system suspend currently in progress to be aborted or wake up the system if already suspended. However, after suspend_device_irqs() interrupt handlers are not executed for system wakeup IRQs. They are only executed for IRQF_NO_SUSPEND IRQs at that time, but those IRQs should not be configured for system wakeup using enable_irq_wake().”…””}”(hj°hj®hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KXhjehžhubeh}”(h]”Œ=system-wakeup-interrupts-enable-irq-wake-and-disable-irq-wake”ah ]”h"]”ŒBsystem wakeup interrupts, enable_irq_wake() and disable_irq_wake()”ah$]”h&]”uh1h¡hh£hžhhŸh¶h K;ubh¢)”}”(hhh]”(h§)”}”(hŒInterrupts and Suspend-to-Idle”h]”hŒInterrupts and Suspend-to-Idle”…””}”(hjÉhjÇhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjÄhžhhŸh¶h Kaubh¸)”}”(hŒÚSuspend-to-idle (also known as the "freeze" sleep state) is a relatively new system sleep state that works by idling all of the processors and waiting for interrupts right after the "noirq" phase of suspending devices.”h]”hŒâSuspend-to-idle (also known as the “freeze†sleep state) is a relatively new system sleep state that works by idling all of the processors and waiting for interrupts right after the “noirq†phase of suspending devices.”…””}”(hj×hjÕhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KchjÄhžhubh¸)”}”(hŒÉOf course, this means that all of the interrupts with the IRQF_NO_SUSPEND flag set will bring CPUs out of idle while in that state, but they will not cause the IRQ subsystem to trigger a system wakeup.”h]”hŒÉOf course, this means that all of the interrupts with the IRQF_NO_SUSPEND flag set will bring CPUs out of idle while in that state, but they will not cause the IRQ subsystem to trigger a system wakeup.”…””}”(hjåhjãhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KghjÄhžhubh¸)”}”(hXkSystem wakeup interrupts, in turn, will trigger wakeup from suspend-to-idle in analogy with what they do in the full system suspend case. The only difference is that the wakeup from suspend-to-idle is signaled using the usual working state interrupt delivery mechanisms and doesn't require the platform to use any special interrupt handling logic for it to work.”h]”hXmSystem wakeup interrupts, in turn, will trigger wakeup from suspend-to-idle in analogy with what they do in the full system suspend case. The only difference is that the wakeup from suspend-to-idle is signaled using the usual working state interrupt delivery mechanisms and doesn’t require the platform to use any special interrupt handling logic for it to work.”…””}”(hjóhjñhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KkhjÄhžhubeh}”(h]”Œinterrupts-and-suspend-to-idle”ah ]”h"]”Œinterrupts and suspend-to-idle”ah$]”h&]”uh1h¡hh£hžhhŸh¶h Kaubh¢)”}”(hhh]”(h§)”}”(hŒ%IRQF_NO_SUSPEND and enable_irq_wake()”h]”hŒ%IRQF_NO_SUSPEND and enable_irq_wake()”…””}”(hj hj hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjhžhhŸh¶h Ksubh¸)”}”(hŒ£There are very few valid reasons to use both enable_irq_wake() and the IRQF_NO_SUSPEND flag on the same IRQ, and it is never valid to use both for the same device.”h]”hŒ£There are very few valid reasons to use both enable_irq_wake() and the IRQF_NO_SUSPEND flag on the same IRQ, and it is never valid to use both for the same device.”…””}”(hjhjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Kuhjhžhubh¸)”}”(hX"First of all, if the IRQ is not shared, the rules for handling IRQF_NO_SUSPEND interrupts (interrupt handlers are invoked after suspend_device_irqs()) are directly at odds with the rules for handling system wakeup interrupts (interrupt handlers are not invoked after suspend_device_irqs()).”h]”hX"First of all, if the IRQ is not shared, the rules for handling IRQF_NO_SUSPEND interrupts (interrupt handlers are invoked after suspend_device_irqs()) are directly at odds with the rules for handling system wakeup interrupts (interrupt handlers are not invoked after suspend_device_irqs()).”…””}”(hj(hj&hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Kyhjhžhubh¸)”}”(hŒóSecond, both enable_irq_wake() and IRQF_NO_SUSPEND apply to entire IRQs and not to individual interrupt handlers, so sharing an IRQ between a system wakeup interrupt source and an IRQF_NO_SUSPEND interrupt source does not generally make sense.”h]”hŒóSecond, both enable_irq_wake() and IRQF_NO_SUSPEND apply to entire IRQs and not to individual interrupt handlers, so sharing an IRQ between a system wakeup interrupt source and an IRQF_NO_SUSPEND interrupt source does not generally make sense.”…””}”(hj6hj4hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K~hjhžhubh¸)”}”(hXIn rare cases an IRQ can be shared between a wakeup device driver and an IRQF_NO_SUSPEND user. In order for this to be safe, the wakeup device driver must be able to discern spurious IRQs from genuine wakeup events (signalling the latter to the core with pm_system_wakeup()), must use enable_irq_wake() to ensure that the IRQ will function as a wakeup source, and must request the IRQ with IRQF_COND_SUSPEND to tell the core that it meets these requirements. If these requirements are not met, it is not valid to use IRQF_COND_SUSPEND.”h]”hXIn rare cases an IRQ can be shared between a wakeup device driver and an IRQF_NO_SUSPEND user. In order for this to be safe, the wakeup device driver must be able to discern spurious IRQs from genuine wakeup events (signalling the latter to the core with pm_system_wakeup()), must use enable_irq_wake() to ensure that the IRQ will function as a wakeup source, and must request the IRQ with IRQF_COND_SUSPEND to tell the core that it meets these requirements. If these requirements are not met, it is not valid to use IRQF_COND_SUSPEND.”…””}”(hjDhjBhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Kƒhjhžhubeh}”(h]”Œ#irqf-no-suspend-and-enable-irq-wake”ah ]”h"]”Œ%irqf_no_suspend and enable_irq_wake()”ah$]”h&]”uh1h¡hh£hžhhŸh¶h Ksubeh}”(h]”Œ$system-suspend-and-device-interrupts”ah ]”h"]”Œ$system suspend and device interrupts”ah$]”h&]”uh1h¡hhhžhhŸh¶h Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”h¶uh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(h¦NŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”jƒŒerror_encoding”ŒUTF-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”h¶Œ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œ embed_images”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(j]jZjjjbj_jÁj¾jjjUjRuŒ nametypes”}”(j]NjNjbNjÁNjNjUNuh}”(jZh£jhßj_j"j¾jejjÄjRjuŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nhžhub.