<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://elinux.org/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://elinux.org/index.php?title=Pm_Sub_System&amp;feed=atom&amp;action=history</id>
		<title>Pm Sub System - Revision history</title>
		<link rel="self" type="application/atom+xml" href="http://elinux.org/index.php?title=Pm_Sub_System&amp;feed=atom&amp;action=history"/>
		<link rel="alternate" type="text/html" href="http://elinux.org/index.php?title=Pm_Sub_System&amp;action=history"/>
		<updated>2013-06-20T11:20:42Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.22alpha</generator>

	<entry>
		<id>http://elinux.org/index.php?title=Pm_Sub_System&amp;diff=71917&amp;oldid=prev</id>
		<title>Peter Huewe at 21:20, 27 October 2011</title>
		<link rel="alternate" type="text/html" href="http://elinux.org/index.php?title=Pm_Sub_System&amp;diff=71917&amp;oldid=prev"/>
				<updated>2011-10-27T21:20:07Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table class='diff diff-contentalign-left'&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
			&lt;tr style='vertical-align: top;'&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black; text-align: center;&quot;&gt;Revision as of 21:20, 27 October 2011&lt;/td&gt;
			&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color:black; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;#160;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== [[Pm Sub System]] ==&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== [[Pm Sub System]] ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 432:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 431:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;#160; - What is relationship between LDM and kobjects?&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;#160; - What is relationship between LDM and kobjects?&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* The &amp;quot;Kobject&amp;quot; is an abstruction of hierarchical structured instance in the kernel. Each object has own name and refrence count, may have children and a parent, can be put into hierarchical tree and removed from it. &amp;quot;Kset&amp;quot; represents a set of &amp;quot;Kobject&amp;quot;. [[Sys Fs]] is designed to provide methods to acccess &amp;quot;Kobject&amp;quot;.In other word, from user space, program can communicate each object thorugh [[Sys Fs]] name sapce. LDM utilizes &amp;quot;&amp;quot;Kobject&amp;quot;&amp;quot; to maintain appearance of devices.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* The &amp;quot;Kobject&amp;quot; is an abstruction of hierarchical structured instance in the kernel. Each object has own name and refrence count, may have children and a parent, can be put into hierarchical tree and removed from it. &amp;quot;Kset&amp;quot; represents a set of &amp;quot;Kobject&amp;quot;. [[Sys Fs]] is designed to provide methods to acccess &amp;quot;Kobject&amp;quot;.In other word, from user space, program can communicate each object thorugh [[Sys Fs]] name sapce. LDM utilizes &amp;quot;&amp;quot;Kobject&amp;quot;&amp;quot; to maintain appearance of devices.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;#160;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color:black; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;#160;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color:black; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;#160;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color:black; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[[Category:Power Management]]&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Peter Huewe</name></author>	</entry>

	<entry>
		<id>http://elinux.org/index.php?title=Pm_Sub_System&amp;diff=2046&amp;oldid=prev</id>
		<title>RBot: Bot (Edward's framework)</title>
		<link rel="alternate" type="text/html" href="http://elinux.org/index.php?title=Pm_Sub_System&amp;diff=2046&amp;oldid=prev"/>
				<updated>2007-03-06T03:35:43Z</updated>
		
		<summary type="html">&lt;p&gt;Bot (Edward&amp;#039;s framework)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
== [[Pm Sub System]] ==&lt;br /&gt;
This document describes OLD and NEW PM model in linux kernel 2.6.8.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== OLD PM model ===&lt;br /&gt;
&lt;br /&gt;
This interface set cannot handle appropriately power dependencies &lt;br /&gt;
constrained by geometrical connections. For example, PCI&lt;br /&gt;
devices have to be turned off before the PCI bus turned off.&lt;br /&gt;
So new interfaces which work with LDM have been introduced in 2.6.x to replace&lt;br /&gt;
the following OLD PM interfaces (now) in &amp;quot;kernel/power/pm.c&amp;quot;. (These routines&lt;br /&gt;
were in the file kernel/pm.c in 2.4.x)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pm_register();&lt;br /&gt;
pm_unregister();&lt;br /&gt;
pm_unregister_all();&lt;br /&gt;
pm_send();&lt;br /&gt;
pm_send_all();&lt;br /&gt;
pm_find();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also, device drivers were requested to make calls to &amp;lt;code&amp;gt;{pm_access()&amp;lt;/code&amp;gt; when&lt;br /&gt;
they accessed their devices, and &amp;lt;code&amp;gt;pm_dev_idle()&amp;lt;/code&amp;gt; when a device was not&lt;br /&gt;
being used, so the system could keep track of device and system idleness.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pm_access();&lt;br /&gt;
pm_dev_idle();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Register handlers ====&lt;br /&gt;
Device drivers may register a callback handler for each device driver, using&lt;br /&gt;
pm_register(). The callback handler is required to handle both the suspend and resume&lt;br /&gt;
operations. The handler is placed on the double linked&lt;br /&gt;
list &amp;quot;pm_devs&amp;quot; with this function.&lt;br /&gt;
&lt;br /&gt;
==== Call handlers ====&lt;br /&gt;
The PM subsystem sends PM messages to the registered handlers by calling&lt;br /&gt;
the routines pm_send() and pm_send_all().&lt;br /&gt;
For example, the APM routines under &amp;quot;arch/i386/kernel/apm.c&amp;quot; demonstrates the use of&lt;br /&gt;
pm_send_all().&lt;br /&gt;
&lt;br /&gt;
The routine pm_send_all() calls all the handlers registered with pm_register(), &lt;br /&gt;
in the order they were registered.&lt;br /&gt;
Please refer &amp;quot;kernel/power/pm.c&amp;quot; for details.&lt;br /&gt;
&lt;br /&gt;
''Note that in 2.4, apm.c::suspend() only called pm_send_all(), but in 2.6 it&lt;br /&gt;
now calls pm_send_all(), followed by calls to device_suspend(3) and device_power_down(3).&lt;br /&gt;
 TRB''&lt;br /&gt;
&lt;br /&gt;
==== API of handler ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int suspend_resume_callback_handler(struct pm_dev *, pm_request_t, void *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  1st arg: target device&lt;br /&gt;
  2nd arg: request type&lt;br /&gt;
    PM_SUSPEND&lt;br /&gt;
    PM_RESUME&lt;br /&gt;
  3rd arg: place holder for extra data&lt;br /&gt;
&lt;br /&gt;
  return values:&lt;br /&gt;
    0 ... success&lt;br /&gt;
    otherwise ... fail&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== NEW PM model ===&lt;br /&gt;
&lt;br /&gt;
The PM model has been modified in 2.6 to work with LDM (Linux Device Model)&lt;br /&gt;
Most devices are connected to the system through a bus, and power management&lt;br /&gt;
operations on such devices need to work in conjunction with code which&lt;br /&gt;
manages the related.&lt;br /&gt;
&lt;br /&gt;
==== Register handlers ====&lt;br /&gt;
LDM records a separate suspend and resume handler routine for each bus type as&lt;br /&gt;
parts of its own structure, of type &amp;quot;struct bus_type&amp;quot;, using bus_register(),&lt;br /&gt;
&lt;br /&gt;
E.g drivers/pci/pci-driver.c&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    struct bus_type pci_bus_type = {&lt;br /&gt;
            .name           = &amp;quot;pci&amp;quot;,&lt;br /&gt;
            .match          = pci_bus_match,&lt;br /&gt;
            .hotplug        = pci_hotplug,&lt;br /&gt;
            .suspend        = pci_device_suspend,&lt;br /&gt;
            .resume         = pci_device_resume,&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    static int __init pci_driver_init(void)&lt;br /&gt;
    {&lt;br /&gt;
            return bus_register(&amp;amp;pci_bus_type);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
Each bus driver has a device register function, like&lt;br /&gt;
platform_device_register() in drivers/base/platform.c&lt;br /&gt;
(The platform_device_register() registers devices under &amp;quot;Platform.&amp;quot;&lt;br /&gt;
&amp;quot;Platform&amp;quot; abstracts unstructured device connections and&lt;br /&gt;
legacy device connections.)&lt;br /&gt;
&lt;br /&gt;
Each device driver can register their own suspend and resume handlers&lt;br /&gt;
through the bus specific device register function, describe as above.&lt;br /&gt;
Each bus device driver could have bus-specific  device-suspend, &lt;br /&gt;
device-resume handler and  handler-register-function.&lt;br /&gt;
That means the interfaces for those function could be different for each bus &lt;br /&gt;
type.&lt;br /&gt;
&lt;br /&gt;
E.g.&lt;br /&gt;
For PCI,  drivers/pci/pci-driver.c:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    static int pci_device_suspend(struct device * dev, u32 state)&lt;br /&gt;
    {&lt;br /&gt;
            struct pci_dev * pci_dev = to_pci_dev(dev);&lt;br /&gt;
            struct pci_driver * drv = pci_dev-&amp;gt;driver;&lt;br /&gt;
    &lt;br /&gt;
            if (drv &amp;amp;&amp;amp; drv-&amp;gt;suspend)&lt;br /&gt;
                    return drv-&amp;gt;suspend(pci_dev,state);&lt;br /&gt;
            return 0;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For &amp;quot;Platform&amp;quot;, drivers/base/platform.c:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    static int platform_suspend(struct device * dev, u32 state)&lt;br /&gt;
    {&lt;br /&gt;
            int ret = 0;&lt;br /&gt;
    &lt;br /&gt;
            if (dev-&amp;gt;driver &amp;amp;&amp;amp; dev-&amp;gt;driver-&amp;gt;suspend) {&lt;br /&gt;
                    ret = dev-&amp;gt;driver-&amp;gt;suspend(dev, state,&lt;br /&gt;
                    SUSPEND_DISABLE);&lt;br /&gt;
                    if (ret == 0)&lt;br /&gt;
                            ret = dev-&amp;gt;driver-&amp;gt;suspend(dev, state, SUSPEND_SAVE_STATE);&lt;br /&gt;
                    if (ret == 0)&lt;br /&gt;
                            ret = dev-&amp;gt;driver-&amp;gt;suspend(dev, state, SUSPEND_POWER_DOWN);&lt;br /&gt;
            }&lt;br /&gt;
            return ret;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Call handlers ====&lt;br /&gt;
&lt;br /&gt;
The PM code in the 2.6 kernel is based on Software Suspend/Resume Open Source &lt;br /&gt;
project, mentioned as &amp;quot;swsusp&amp;quot;. The design of &amp;quot;swsusp&amp;quot; is  deeply &lt;br /&gt;
influenced by ACPI. Most code assumes the power state value &amp;quot;0&amp;quot;&lt;br /&gt;
means power-on corresponding D0 state of ACPI and &amp;quot;3&amp;quot; means &lt;br /&gt;
power-off corresponding to D3 state of ACPI respectively.&lt;br /&gt;
    &lt;br /&gt;
There are two ways of controlling device power. One is a Device Power&lt;br /&gt;
Management, called as Device PM or DPM in short. Another is System &lt;br /&gt;
Level Power Management. We refer to this as System PM.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Internal Sequence of Device PM =====&lt;br /&gt;
&lt;br /&gt;
With Device PM, user can now turn on and off individual devices through&lt;br /&gt;
the /sys interface.&lt;br /&gt;
&lt;br /&gt;
For example, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
% echo 3 &amp;gt; /sys/bus/usb/devices/1-1/power/state&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
means turning off the specified device.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
% echo  n &amp;gt; /sys/bus/usb/devices/1-1/power/state&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*** when n == 0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    state_store()            [drivers/base/power/sysfs.c]&lt;br /&gt;
         -&amp;gt;&lt;br /&gt;
        dpm_runtime_suspend()    [drivers/base/power/runtime.c]&lt;br /&gt;
             -&amp;gt;&lt;br /&gt;
            suspend_device()    // suspend specified device&lt;br /&gt;
                    [drivers/base/power/suspend.c]&lt;br /&gt;
                 -&amp;gt;&lt;br /&gt;
                call suspend handler of the bus which the specified&lt;br /&gt;
                    device belongs to .                &lt;br /&gt;
             -&amp;gt;&lt;br /&gt;
                    call suspend handler for the specified device&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
** when n = 0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    state_store()            [drivers/base/power/sysfs.c]&lt;br /&gt;
     -&amp;gt; dpm_runtime_resume()    [drivers/base/power/runtime.c]&lt;br /&gt;
         -&amp;gt; runtime_resume()    [driver/base/power/runtime.c]&lt;br /&gt;
             -&amp;gt; resume_device()    // resume specified device&lt;br /&gt;
                    [driver/base/power/resume.c]&lt;br /&gt;
                     -&amp;gt; call resume handler of the bus which the specified&lt;br /&gt;
                       device belongs to .                &lt;br /&gt;
            -&amp;gt; call resume handler for the specified device&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
===== Internal Sequence of System PM =====&lt;br /&gt;
&lt;br /&gt;
With System Level PM, user can turn off and on the entire system.&lt;br /&gt;
This interface is &lt;br /&gt;
implemented as /sys/power/state and pm_suspend().&lt;br /&gt;
There is no mechanism  for a System level resume, because there is&lt;br /&gt;
no way for a suspended system to initiate a resume from software.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
% echo &amp;quot;standby&amp;quot; &amp;gt; /sys/power/state &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    state_store()            [kernel/power/main.c]&lt;br /&gt;
    -&amp;gt; enter_state()        [kernel/power/main.c]&lt;br /&gt;
           :&lt;br /&gt;
     go with the same route when pm_suspend() called&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pm_suspend()                [kernel/power/main.c]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    enter_state()            [kernel/power/main.c]&lt;br /&gt;
    -&amp;gt;suspend_prepare()        [kernel/power/main.c]&lt;br /&gt;
      -&amp;gt;&lt;br /&gt;
        pm_prepare_console()    [kernel/power/console.c]&lt;br /&gt;
        freeze_processes()        [kernel/power/process.c]&lt;br /&gt;
        pm_ops-&amp;gt;prepare()&lt;br /&gt;
        device_suspend()        // called with &amp;quot;irq on&amp;quot;    &lt;br /&gt;
                    [driver/base/power/suspend.c] &lt;br /&gt;
        -&amp;gt;&lt;br /&gt;
          suspend_device(), foreach device on the &amp;quot;dpm_active&amp;quot; list &lt;br /&gt;
                    [driver/base/power/suspend.c] &lt;br /&gt;
          move the entry from &amp;quot;dpm_active&amp;quot; to &amp;quot;dpm_off&amp;quot;  &lt;br /&gt;
          or &amp;quot;dpm_off_irq&amp;quot; on suspend handler returns -EAGAIN&lt;br /&gt;
          &lt;br /&gt;
      suspend_enter()        [kernel/power/main.c]&lt;br /&gt;
      -&amp;gt;&lt;br /&gt;
        local_irq_save()&lt;br /&gt;
        device_power_down()     // called with &amp;quot;irq off&amp;quot;&lt;br /&gt;
                    [drivers/base/power/suspend.c] &lt;br /&gt;
        -&amp;gt;&lt;br /&gt;
          suspend_device(), foreach device on the &amp;quot;dpm_off_irq&amp;quot; list&lt;br /&gt;
                    [drivers/base/power/suspend.c] &lt;br /&gt;
          sysdev_suspend()        [drivers/base/sys.c]&lt;br /&gt;
        pm_ops-&amp;gt;enter()        // System will down here&lt;br /&gt;
        device_power_up()          // called with &amp;quot;irq off&amp;quot;&lt;br /&gt;
                    [drivers/base/power/resume.c] &lt;br /&gt;
        -&amp;gt;&lt;br /&gt;
          sysdev_resume()        [drivers/base/sys.c]&lt;br /&gt;
          dpm_power_up()        [drivers/base/power/resume.c] &lt;br /&gt;
          -&amp;gt;&lt;br /&gt;
        resume_device(), foreach device on the &amp;quot;dpm_off_irq&amp;quot; list&lt;br /&gt;
                    [driver/base/power/suspend.c] &lt;br /&gt;
        move the entry from &amp;quot;dpm_irq_off&amp;quot; to &amp;quot;dpm_active&amp;quot;  &lt;br /&gt;
        local_irq_restore()&lt;br /&gt;
      suspend_finish()        [kernel/power/main.c]&lt;br /&gt;
      -&amp;gt;&lt;br /&gt;
        device_resume()        // called with &amp;quot;irq on&amp;quot; &lt;br /&gt;
                    [drivers/base/power/resume.c] &lt;br /&gt;
        -&amp;gt;&lt;br /&gt;
          dpm_resume()        [drivers/base/power/resume.c] &lt;br /&gt;
          -&amp;gt;&lt;br /&gt;
        resume_device(), foreach device on the &amp;quot;dpm_off&amp;quot; list.&lt;br /&gt;
        move the entry to &amp;quot;dpm_active&amp;quot; from &amp;quot;dpm_off&amp;quot;&lt;br /&gt;
        pm_ops-&amp;gt;finish()        // target PM specific&lt;br /&gt;
        thaw_processes()        [kernel/power/process.c]&lt;br /&gt;
        pm_restore_console()    [kernel/power/console.c]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
suspend_device()        [drivers/base/power/suspend.c] &lt;br /&gt;
    -&amp;gt;&lt;br /&gt;
      call suspend handler the bus which the specified&lt;br /&gt;
          device belongs to .&lt;br /&gt;
      -&amp;gt;&lt;br /&gt;
        call suspend handler for the specified device&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysdev_suspend()          [drivers/base/sys.c]&lt;br /&gt;
      for each kernel susbsys and class&lt;br /&gt;
        call suspend handler for each driver on &amp;quot;global_drivers&amp;quot;, &lt;br /&gt;
          registered with sysdev_register().&lt;br /&gt;
        call a suspend handler for each driver under the class.&lt;br /&gt;
        call a suspend handler for the class&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysdev_resume()        [drivers/base/sys.c]&lt;br /&gt;
      for each kernel susbsys and class&lt;br /&gt;
        call a resume handler for the class&lt;br /&gt;
        call a resume handler for each driver under &lt;br /&gt;
        the class.&lt;br /&gt;
        call resume handler for each driver on &amp;quot;global_drivers&amp;quot;, &lt;br /&gt;
        registered with sysdev_register().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
resume_device()        [drivers/base/power/resume.c]&lt;br /&gt;
    -&amp;gt;&lt;br /&gt;
      call resume handler of the bus which the specified &lt;br /&gt;
          device belongs to.&lt;br /&gt;
      -&amp;gt;&lt;br /&gt;
        call resume handler for the specified device&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== API of handlers ====&lt;br /&gt;
Following two methods are prepared in struct &amp;quot;bus_types&amp;quot; in include/linx/pm.h&lt;br /&gt;
to hold bus specific suspend/resume handlers for adapting device suspend/resume&lt;br /&gt;
methods to bus specific ways.&lt;br /&gt;
&lt;br /&gt;
First, the PM subsystem calls looks up the bus, which the specified device belongs to.&lt;br /&gt;
Then it calls bus specific suspend/resume handler to suspend/resume the specified&lt;br /&gt;
device. In most case, bus specific suspend/resume handler calls the device specific&lt;br /&gt;
suspend/resume handler.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct bus_types {&lt;br /&gt;
                            :&lt;br /&gt;
                            :&lt;br /&gt;
      int        (*suspend)(struct device * dev, u32 state);&lt;br /&gt;
      int        (*resume)(struct device * dev);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
      (*suspend)()&lt;br /&gt;
        1st arg: target device&lt;br /&gt;
        2nd arg: PM state to be entered&lt;br /&gt;
            PM_SUSPEND_STANDBY, &lt;br /&gt;
            PM_SUSPEND_MEM,&lt;br /&gt;
            PM_SUSPEND_DISK&lt;br /&gt;
&lt;br /&gt;
        return values:&lt;br /&gt;
        0 ... success&lt;br /&gt;
        -EAGAIN ... try again later with &amp;quot;irq_off&amp;quot;&lt;br /&gt;
        otherwise ... fail&lt;br /&gt;
&lt;br /&gt;
    (*resume)()&lt;br /&gt;
        1st arg: target device&lt;br /&gt;
        return values:&lt;br /&gt;
        0 ... success&lt;br /&gt;
        otherwise ... fail&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== PM_OPS ====&lt;br /&gt;
&lt;br /&gt;
Target PM subsystem stands for the instance of PM subsystem&lt;br /&gt;
presented on target system, adopting underlaying hardware and&lt;br /&gt;
software requirements, like ACPI or APM.&lt;br /&gt;
&lt;br /&gt;
PM_OPS provides target PM subsystem specific mthods to prepare, enter and finish  supsend.&lt;br /&gt;
&lt;br /&gt;
For example, the ACPI PM subsystem uses the following method, in &lt;br /&gt;
drivers/acpi/sleep/main.c&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static struct pm_ops acpi_pm_ops = {&lt;br /&gt;
        .prepare        = acpi_pm_prepare,&lt;br /&gt;
        .enter          = acpi_pm_enter,&lt;br /&gt;
        .finish         = acpi_pm_finish,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 - prepare()&lt;br /&gt;
  prepare() perform a target PM susbsystem specific prepareation before suspend.&lt;br /&gt;
  prepare() usually checks the state to be entered. prepare() has to return &lt;br /&gt;
  non-zero value, if operation was failed.&lt;br /&gt;
&lt;br /&gt;
 - enter()&lt;br /&gt;
  enter() provide a target PM susbsystem specific method to suspend. &lt;br /&gt;
  For example, acpi_pm_enter() calls ACPI bios serivce.&lt;br /&gt;
  Platform will stop/sleep in enter().  enter() has to return non-zero value,&lt;br /&gt;
  if operation was failed.&lt;br /&gt;
&lt;br /&gt;
 - finish()&lt;br /&gt;
  finish() perform a PM susbsystem specific post-processing after platform &lt;br /&gt;
  comes back or prepare() failed. finish() has to return non-zero value,&lt;br /&gt;
  if operation was failed.&lt;br /&gt;
&lt;br /&gt;
== Resources ==&lt;br /&gt;
 - I found the following paper while I was researching this information, however&lt;br /&gt;
   it is a little old and seems to be out of date.&lt;br /&gt;
   - [http://archive.linuxsymposium.org/ols2003/Proceedings/All-Reprints/Reprint-Mochel-OLS2003.pdf Linux Kernel Power Management] - Patrick Mochel, Open Source Development Labs&lt;br /&gt;
&lt;br /&gt;
== Questions ==&lt;br /&gt;
 - What are the function in pm_ops for?&lt;br /&gt;
* PM_OPS provides target PM subsystem specific mthods to prepare, enter and finish supsend.&lt;br /&gt;
&lt;br /&gt;
 - What is relationship between LDM and kobjects?&lt;br /&gt;
* The &amp;quot;Kobject&amp;quot; is an abstruction of hierarchical structured instance in the kernel. Each object has own name and refrence count, may have children and a parent, can be put into hierarchical tree and removed from it. &amp;quot;Kset&amp;quot; represents a set of &amp;quot;Kobject&amp;quot;. [[Sys Fs]] is designed to provide methods to acccess &amp;quot;Kobject&amp;quot;.In other word, from user space, program can communicate each object thorugh [[Sys Fs]] name sapce. LDM utilizes &amp;quot;&amp;quot;Kobject&amp;quot;&amp;quot; to maintain appearance of devices.&lt;/div&gt;</summary>
		<author><name>RBot</name></author>	</entry>

	</feed>