Writing Solaris Device Driver: Power Management

Power Management

Power management provides the ability to control and manage the electrical power usage of a computer system or device. Power management enables systems to conserve energy by using less power when idle and by shutting down completely when not in use. For example, desktop computer systems can use a significant amount of power and often are left idle, particularly at night. Power management software can detect that the system is not being used. Accordingly, power management can power down the system or some of its components.

This chapter provides information on the following subjects:

Power Management Framework

The Solaris Power ManagementTM framework depends on device drivers to implement device-specific power management functions. The framework is implemented in two parts:

  • Device power management – Automatically turns off unused devices to reduce power consumption

  • System power management – Automatically turns off the computer when the entire system is idle

Device Power Management

The framework enables devices to reduce their energy consumption after a specified idle time interval. As part of power management, system software checks for idle devices. The Power Management framework exports interfaces that enable communication between the system software and the device driver.

The Solaris Power Management framework provides the following features for device power management:

  • A device-independent model for power-manageable devices.

  • dtpower(1M), a tool for configuring workstation power management. Power management can also be implemented through the power.conf(4) and /etc/default/power files.

  • A set of DDI interfaces for notifying the framework about power management compatibility and idleness state.

System Power Management

System power management involves saving the state of the system prior to powering the system down. Thus, the system can be returned to the same state immediately when the system is turned back on.

To shut down an entire system with return to the state prior to the shutdown, take the following steps:

  • Stop kernel threads and user processes. Restart these threads and processes later.

  • Save the hardware state of all devices on the system to disk. Restore the state later.


SPARC only –

System power management is currently implemented only on some SPARC systems supported by the Solaris operating system. See the power.conf(4) man page for more information.


The System Power Management framework in the Solaris operating system provides the following features for system power management:

  • A platform-independent model of system idleness.

  • pmconfig(1M), a tool for configuring workstation power management. Power management can also be implemented through the power.conf(4) and /etc/default/power files.

  • A set of interfaces for the device driver to override the method for determining which drivers have hardware state.

  • A set of interfaces to enable the framework to call into the driver to save and restore the device state.

  • A mechanism for notifying processes that a resume operation has occurred.

Device Power Management Model

The following sections describe the details of the device power management model. This model includes the following elements:

  • Components

  • Idleness

  • Power levels

  • Dependency

  • Policy

  • Device power management interfaces

  • Power management entry points

Power Management Components

A device is power manageable if the power consumption of the device can be reduced when the device is idle. Conceptually, a power-manageable device consists of a number of power-manageable hardware units that are called components.

The device driver notifies the system about device components and their associated power levels. Accordingly, the driver creates a pm-components(9P) property in the driver's attach(9E) entry point as part of driver initialization.

Most devices that are power manageable implement only a single component. An example of a single-component, power-manageable device is a disk whose spindle motor can be stopped to save power when the disk is idle.

If a device has multiple power-manageable units that are separately controllable, the device should implement multiple components.

An example of a two-component, power-manageable device is a frame buffer card with a monitor. Frame buffer electronics is the first component [component 0]. The frame buffer's power consumption can be reduced when not in use. The monitor is the second component [component 1]. The monitor can also enter a lower power mode when the monitor is not in use. The frame buffer electronics and monitor are considered by the system as one device with two components.

Multiple Power Management Components

To the power management framework, all components are considered equal and completely independent of each other. If the component states are not completely compatible, the device driver must ensure that undesirable state combinations do not occur. For example, a frame buffer/monitor card has the following possible states: D0, D1, D2, and D3. The monitor attached to the card has the following potential states: On, Standby, Suspend, and Off. These states are not necessarily compatible with each other. For example, if the monitor is On, then the frame buffer must be at D0, that is, full on. If the frame buffer driver gets a request to power up the monitor to On while the frame buffer is at D3, the driver must call pm_raise_power(9F) to bring the frame buffer up before setting the monitor On. System requests to lower the power of the frame buffer while the monitor is On must be refused by the driver.

Power Management States

Each component of a device can be in one of two states: busy or idle. The device driver notifies the framework of changes in the device state by calling pm_busy_component(9F) and pm_idle_component(9F). When components are initially created, the components are considered idle.

Power Levels

From the pm-components property exported by the device, the Device Power Management framework knows what power levels the device supports. Power-level values must be positive integers. The interpretation of power levels is determined by the device driver writer. Power levels must be listed in monotonically increasing order in the pm-components property. A power level of 0 is interpreted by the framework to mean off. When the framework must power up a device due to a dependency, the framework sets each component at its highest power level.

The following example shows a pm-components entry from the .conf file of a driver that implements a single power-managed component consisting of a disk spindle motor. The disk spindle motor is component 0. The spindle motor supports two power levels. These levels represent “stopped” and “spinning at full speed.”


Example 12–1 Sample pm-component Entry

pm-components="NAME=Spindle Motor", "0=Stopped", "1=Full Speed";

The following example shows how Example 12–1 could be implemented in the attach() routine of the driver.


Example 12–2 attach(9E) Routine With pm-components Property

static char *pmcomps[] = {
"NAME=Spindle Motor",
"0=Stopped",
"1=Full Speed"
};

...

xxattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
...
if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip,
"pm-components", &pmcomp[0],
sizeof (pmcomps) / sizeof (char *)) != DDI_PROP_SUCCESS)
goto failed;
...

The following example shows a frame buffer that implements two components. Component 0 is the frame buffer electronics that support four different power levels. Component 1 represents the state of power management of the attached monitor.


Example 12–3 Multiple Component pm-components Entry

pm-components="NAME=Frame Buffer", "0=Off", "1=Suspend", /
"2=Standby", "3=On",
"NAME=Monitor", "0=Off", "1=Suspend", "2=Standby", "3=On";

When a device driver is first attached, the framework does not know the power level of the device. A power transition can occur when:

After a power transition, the framework begins tracking the power level of each component of the device. Tracking also occurs if the driver has informed the framework of the power level. The driver informs the framework of a power level change by calling pm_power_has_changed(9F).

The system calculates a default threshold for each potential power transition. These thresholds are based on the system idleness threshold. The default thresholds can be overridden using pmconfig or power.conf(4). Another default threshold based on the system idleness threshold is used when the component power level is unknown.

Power Management Dependencies

Some devices should be powered down only when other devices are also powered down. For example, if a CD-ROM drive is allowed to power down, necessary functions, such as the ability to eject a CD, might be lost.

To prevent a device from powering down independently, you can make that device dependent on another device that is likely to remain powered on. Typically, a device is made dependent upon a frame buffer, because a monitor is generally on whenever a user is utilizing a system.

The power.conf(4)file specifies the dependencies among devices. (A parent node in the device tree implicitly depends upon its children. This dependency is handled automatically by the power management framework.) You can specify a particular dependency with a power.conf(4) entry of this form:

device-dependency dependent-phys-path phys-path 

Where dependent-phys-path is the device that is kept powered up, such as the CD-ROM drive. phys-path represents the device whose power state is to be depended on, such as the frame buffer.

Adding an entry to power.conf for every new device that is plugged into the system would be burdensome. The following syntax enables you to indicate dependency in a more general fashion:

device-dependency-property property phys-path 

Such an entry mandates that any device that exports the property property must be dependent upon the device named by phys-path. Because this dependency applies especially to removable-media devices, /etc/power.conf includes the following line by default:

device_dependent-property  removable-media  /dev/fb

With this syntax, no device that exports the removable-media property can be powered down unless the console frame buffer is also powered down.

For more information, see the power.conf(4) and removable-media(9P) man pages.

Automatic Power Management for Devices

If automatic power management is enabled by pmconfig or power.conf(4), then all devices with a pm-components(9P) property automatically will use power management. After a component has been idle for a default period, the component is automatically lowered to the next lowest power level. The default period is calculated by the power management framework to set the entire device to its lowest power state within the system idleness threshold.


Note –

By default, automatic power management is enabled on all SPARC desktop systems first shipped after July 1, 1999. This feature is disabled by default for all other systems. To determine whether automatic power management is enabled on your machine, refer to the power.conf(4) man page for instructions.


power.conf(4) can be used to override the defaults calculated by the framework.

Device Power Management Interfaces

A device driver that supports a device with power-manageable components must create a pm-components(9P) property. This property indicates to the system that the device has power-manageable components. pm-components also tells the system which power levels are available. The driver typically informs the system by calling ddi_prop_update_string_array(9F) from the driver's attach(9E) entry point. An alternative means of informing the system is from a driver.conf(4) file. See the pm-components(9P) man page for details.

Busy-Idle State Transitions

The driver must keep the framework informed of device state transitions from idle to busy or busy to idle. Where these transitions happen is entirely device-specific. The transitions between the busy and idle states depend on the nature of the device and the abstraction represented by the specific component. For example, SCSI disk target drivers typically export a single component, which represents whether the SCSI target disk drive is spun up or not. The component is marked busy whenever an outstanding request to the drive exists. The component is marked idle when the last queued request finishes. Some components are created and never marked busy. For example, components created by pm-components(9P) are created in an idle state.

The pm_busy_component(9F) and pm_idle_component(9F) interfaces notify the power management framework of busy-idle state transitions. The pm_busy_component(9F) call has the following syntax:

    int pm_busy_component(dev_info_t *dip, int component);

pm_busy_component(9F) marks component as busy. While the component is busy, that component should not be powered off. If the component is already powered off, then marking that component busy does not change the power level. The driver needs to call pm_raise_power(9F) for this purpose. Calls to pm_busy_component(9F) are cumulative and require a corresponding number of calls to pm_idle_component(9F) to idle the component.

The pm_idle_component(9F) routine has the following syntax:

int pm_idle_component(dev_info_t *dip, int component);

pm_idle_component(9F) marks component as idle. An idle component is subject to being powered off. pm_idle_component(9F) must be called once for each call to pm_busy_component(9F) in order to idle the component.

Device Power State Transitions

A device driver can call pm_raise_power(9F) to request that a component be set to at least a given power level. Setting the power level in this manner is necessary before using a component that has been powered off. For example, the read(9E) routine of a SCSI disk target driver might need to spin up the disk, if the disk has been powered off. The pm_raise_power(9F) function requests the power management framework to initiate a device power state transition to a higher power level. Normally, reductions in component power levels are initiated by the framework. However, a device driver should call pm_lower_power(9F) when detaching, in order to reduce the power consumption of unused devices as much as possible.

Powering down can pose risks for some devices. For example, some tape drives damage tapes when power is removed. Similarly, some disk drives have a limited tolerance for power cycles, because each cycle results in a head landing. Use the no-involuntary-power-cycles(9P) property to notify the system that the device driver should control all power cycles for the device. This approach prevents power from being removed from a device while the device driver is detached unless the device was powered off by a driver's call to pm_lower_power(9F) from its detach(9E) entry point.

The pm_raise_power(9F) function is called when the driver discovers that a component needed for some operation is at an insufficient power level. This interface causes the driver to raise the current power level of the component to the needed level. All the devices that depend on this device are also brought back to full power by this call.

Call the pm_lower_power(9F) function when the device is detaching once access to the device is no longer needed. Call pm_lower_power(9F) to set each component at the lowest power so that the device uses as little power as possible while not in use. The pm_lower_power() function must be called from the detach() entry point. The pm_lower_power() function has no effect if it is called from any other part of the driver.

The pm_power_has_changed(9F) function is called to notify the framework about a power transition. The transition might be due to the device changing its own power level. The transition might also be due to an operation such as suspend-resume. The syntax for pm_power_has_changed(9F) is the same as the syntax for pm_raise_power(9F).

power() Entry Point

The power management framework uses the power(9E) entry point.

power() uses the following syntax:

    int power(dev_info_t *dip, int component, int level);

When a component's power level needs to be changed, the system calls the power(9E) entry point. The action taken by this entry point is device driver-specific. In the example of the SCSI target disk driver mentioned previously, setting the power level to 0 results in sending a SCSI command to spin down the disk, while setting the power level to the full power level results in sending a SCSI command to spin up the disk.

If a power transition can cause the device to lose state, the driver must save any necessary state in memory for later restoration. If a power transition requires the saved state to be restored before the device can be used again, then the driver must restore that state. The framework makes no assumptions about what power transactions cause the loss of state or require the restoration of state for automatically power-managed devices. The following example shows a sample power() routine.


Example 12–4 Using the power() Routine for a Single-Component Device

int
xxpower(dev_info_t *dip, int component, int level)
{
struct xxstate *xsp;
int instance;

instance = ddi_get_instance(dip);
xsp = ddi_get_soft_state(statep, instance);
/*
* Make sure the request is valid
*/
if (!xx_valid_power_level(component, level))
return (DDI_FAILURE);
mutex_enter(&xsp->mu);
/*
* If the device is busy, don't lower its power level
*/
if (xsp->xx_busy[component] &&
xsp->xx_power_level[component] > level) {
mutex_exit(&xsp->mu);
return (DDI_FAILURE);
}

if (xsp->xx_power_level[component] != level) {
/*
* device- and component-specific setting of power level
* goes here
*/
[...]
xsp->xx_power_level[component] = level;
}
mutex_exit(&xsp->mu);
return (DDI_SUCCESS);
}

The following example is a power() routine for a device with two components, where component 0 must be on when component 1 is on.


Example 12–5 power(9E) Routine for Multiple-Component Device

int
xxpower(dev_info_t *dip, int component, int level)
{
struct xxstate *xsp;
int instance;

instance = ddi_get_instance(dip);
xsp = ddi_get_soft_state(statep, instance);
/*
* Make sure the request is valid
*/
if (!xx_valid_power_level(component, level))
return (DDI_FAILURE);
mutex_enter(&xsp->mu);
/*
* If the device is busy, don't lower its power level
*/
if (xsp->xx_busy[component] &&
xsp->xx_power_level[component] > level) {
mutex_exit(&xsp->mu);
return (DDI_FAILURE);
}

/*
* This code implements inter-component dependencies:
* If we are bringing up component 1 and component 0
* is off, we must bring component 0 up first, and if
* we are asked to shut down component 0 while component
* 1 is up we must refuse
*/
if (component == 1 && level > 0 && xsp->xx_power_level[0] == 0) {
xsp->xx_busy[0]++;
if (pm_busy_component(dip, 0) != DDI_SUCCESS) {
/*
* This can only happen if the args to
* pm_busy_component()
* are wrong, or pm-components property was not
* exported by the driver.
*/
xsp->xx_busy[0]--;
mutex_exit(&xsp->mu);
cmn_err(CE_WARN, "xxpower pm_busy_component()
failed");
return (DDI_FAILURE);
}
mutex_exit(&xsp->mu);
if (pm_raise_power(dip, 0, XX_FULL_POWER_0) != DDI_SUCCESS)
return (DDI_FAILURE);
mutex_enter(&xsp->mu);
}
if (component == 0 && level == 0 && xsp->xx_power_level[1] != 0) {
mutex_exit(&xsp->mu);
return (DDI_FAILURE);
}
if (xsp->xx_power_level[component] != level) {
/*
* device- and component-specific setting of power level
* goes here
*/
[...]
xsp->xx_power_level[component] = level;
}
mutex_exit(&xsp->mu);
return (DDI_SUCCESS);
}

System Power Management Model

This section describes the details of the System Power Management model. The model includes the following components:

  • Autoshutdown threshold

  • Busy state

  • Hardware state

  • Policy

  • Power management entry points

Autoshutdown Threshold

The system can be shut down, that is, powered off, automatically after a configurable period of idleness. This period is known as the autoshutdown threshold. This behavior is enabled by default for SPARC desktop systems first shipped after October 1, 1995 and before July 1, 1999. See the power.conf(4)man page for more information. Autoshutdown can be overridden using dtpower(1M) or power.conf(4).

Busy State

The busy state of the system can be measured in several ways. The currently supported built-in metric items are keyboard characters, mouse activity, tty characters, load average, disk reads, and NFS requests. Any one of these items can make the system busy. In addition to the built-in metrics, an interface is defined for running a user-specified process that can indicate that the system is busy.

Hardware State

Devices that export a reg property are considered to have hardware state that must be saved prior to shutting down the system. A device without the reg property is considered to be stateless. However, this consideration can be overridden by the device driver.

A device with hardware state but no reg property, such as a SCSI driver, must be called to save and restore the state if the driver exports a pm-hardware-state property with the value needs-suspend-resume. Otherwise, the lack of a reg property is taken to mean that the device has no hardware state. For information on device properties, see Chapter 4, Properties.

A device with a reg property and no hardware state can export a pm-hardware-state property with the value no-suspend-resume. Using no-suspend-resume with the pm-hardware-state property keeps the framework from calling the driver to save and restore that state. For more information on power management properties, see the pm-components(9P) man page.

Automatic Power Management for Systems

The system is shut down if the following conditions apply:

  • Autoshutdown is enabled by dtpower(1M) or power.conf(4).

  • The system has been idle for autoshutdown threshold minutes.

  • All of the metrics that are specified in power.conf have been satisfied.

Entry Points Used by System Power Management

System power management passes the command DDI_SUSPEND to the detach(9E) driver entry point to request the driver to save the device hardware state. System power management passes the command DDI_RESUME to the attach(9E) driver entry point to request the driver to restore the device hardware state.

detach() Entry Point

The syntax for detach(9E) is as follows:

    int detach(dev_info_t *dip, ddi_detach_cmd_t cmd);

A device with a reg property or a pm-hardware-state property set to needs-suspend-resume must be able to save the hardware state of the device. The framework calls into the driver's detach(9E) entry point to enable the driver to save the state for restoration after the system power returns. To process the DDI_SUSPEND command, detach(9E) must perform the following tasks:

  • Block further operations from being initiated until the device is resumed, except for dump(9E) requests.

  • Wait until outstanding operations have completed. If an outstanding operation can be restarted, you can abort that operation.

  • Cancel any timeouts and callbacks that are pending.

  • Save any volatile hardware state to memory. The state includes the contents of device registers, and can also include downloaded firmware.

If the driver is unable to suspend the device and save its state to memory, then the driver must return DDI_FAILURE. The framework then aborts the system power management operation.

In some cases, powering down a device involves certain risks. For example, if a tape drive is powered off with a tape inside, the tape can be damaged. In such a case, attach(9E) should do the following:

  • Call ddi_removing_power(9F) to determine whether a DDI_SUSPEND command can cause power to be removed from the device.

  • Determine whether power removal can cause problems.

If both cases are true, the DDI_SUSPEND request should be rejected. Example 12–6 shows an attach(9E) routine using ddi_removing_power(9F) to check whether the DDI_SUSPEND command causes problems.

Dump requests must be honored. The framework uses the dump(9E) entry point to write out the state file that contains the contents of memory. See the dump(9E) man page for the restrictions that are imposed on the device driver when using this entry point.

Calling the detach(9E) entry point of a power-manageable component with the DDI_SUSPEND command should save the state when the device is powered off. The driver should cancel pending timeouts. The driver should also suppress any calls to pm_raise_power(9F) except for dump(9E) requests. When the device is resumed by a call to attach(9E) with a command of DDI_RESUME, timeouts and calls to pm_raise_power() can be resumed. The driver must keep sufficient track of its state to be able to deal appropriately with this possibility. The following example shows a detach(9E) routine with the DDI_SUSPEND command implemented.


Example 12–6 detach(9E) Routine Implementing DDI_SUSPEND

int
xxdetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
struct xxstate *xsp;
int instance;

instance = ddi_get_instance(dip);
xsp = ddi_get_soft_state(statep, instance);

switch (cmd) {
case DDI_DETACH:
[...]

case DDI_SUSPEND:
/*
* We do not allow DDI_SUSPEND if power will be removed and
* we have a device that damages tape when power is removed
* We do support DDI_SUSPEND for Device Reconfiguration.
.
*/
if (ddi_removing_power(dip) && xxdamages_tape(dip))
return (DDI_FAILURE);

mutex_enter(&xsp->mu);
xsp->xx_suspended = 1; /* stop new operations */

/*
* Sleep waiting for all the commands to be completed
*/
[...]

/*
* If a callback is outstanding which cannot be cancelled
* then either wait for the callback to complete or fail the
* suspend request
*/
[...]

/*
* This section is only needed if the driver maintains a
* running timeout
*/
if (xsp->xx_timeout_id) {
timeout_id_t temp_timeout_id = xsp->xx_timeout_id;

xsp->xx_timeout_id = 0;
mutex_exit(&xsp->mu);
untimeout(temp_timeout_id);
mutex_enter(&xsp->mu);
}

if (!xsp->xx_state_saved) {
/*
* Save device register contents into
* xsp->xx_device_state
*/
[...]
}
mutex_exit(&xsp->mu);
return (DDI_SUCCESS);

default:
return (DDI_FAILURE);
}

attach() Entry Point

The syntax for attach(9E) is as follows:

    int attach(dev_info_t *dip, ddi_attach_cmd_t cmd);

When power is restored to the system, each device with a reg property or with a pm-hardware-state property of value needs-suspend-resume has its attach(9E) entry point called with a command value of DDI_RESUME. If the system shutdown is aborted, each suspended driver is called to resume even though the power has not been shut off. Consequently, the resume code in attach(9E) must make no assumptions about whether the system actually lost power.

The power management framework considers the power level of the components to be unknown at DDI_RESUME time. Depending on the nature of the device, the driver writer has two choices:

  • If the driver can determine the actual power level of the components of the device without powering the components up, such as by reading a register, then the driver should notify the framework of the power level of each component by calling pm_power_has_changed(9F).

  • If the driver cannot determine the power levels of the components, then the driver should mark each component internally as unknown and call pm_raise_power(9F) before the first access to each component.

The following example shows an attach(9E) routine with the DDI_RESUME command.


Example 12–7 attach(9E) Routine Implementing DDI_RESUME

int
xxattach(devinfo_t *dip, ddi_attach_cmd_t cmd)
{
struct xxstate *xsp;
int instance;

instance = ddi_get_instance(dip);
xsp = ddi_get_soft_state(statep, instance);

switch (cmd) {
case DDI_ATTACH:
[...]

case DDI_RESUME:
mutex_enter(&xsp->mu);
if (xsp->xx_pm_state_saved) {
/*
* Restore device register contents from
* xsp->xx_device_state
*/
[...]
}
/*
* This section is optional and only needed if the
* driver maintains a running timeout
*/
xsp->xx_timeout_id = timeout(...);

xsp->xx_suspended = 0; /* allow new operations */
cv_broadcast(&xsp->xx_suspend_cv);

/* If it is possible to determine in a device-specific
* way what the power levels of components are without
* powering the components up,
* then the following code is recommended
*/
for (i = 0; i < num_components; i++) {
xsp->xx_power_level[i] = xx_get_power_level(dip, i);
if (xsp->xx_power_level[i] != XX_LEVEL_UNKNOWN)
(void) pm_power_has_changed(dip, i,
xsp->xx_power_level[i]);
}
mutex_exit(&xsp->mu);
return(DDI_SUCCESS);
default:
return(DDI_FAILURE);
}
}


Note –

The detach(9E) and attach(9E) interfaces can also be used to resume a system that has been quiesced.


Power Management Device Access Example

If power management is supported, and detach(9E) and attach(9E) are used as in Example 12–6 and Example 12–7, then access to the device can be made from user context, for example, from read(2), write(2), and ioctl(2).

The following example demonstrates this approach. The example assumes that the operation about to be performed requires a component component that is operating at power level level.


Example 12–8 Device Access

...
mutex_enter(&xsp->mu);
/*
* Block command while device is suspended by DDI_SUSPEND
*/
while (xsp->xx_suspended)
cv_wait(&xsp->xx_suspend_cv, &xsp->mu);

/*
* Mark component busy so power() will reject attempt to lower power
*/
xsp->xx_busy[component]++;
if (pm_busy_component(dip, component) != DDI_SUCCESS) {
xsp->xx_busy[component]--;
/*
* Log error and abort
*/
[...]
}

if (xsp->xx_power_level[component] < level) {
mutex_exit(&xsp->mu);
if (pm_raise_power(dip, component, level) != DDI_SUCCESS) {
/*
* Log error and abort
*/
[...]
}
mutex_enter(&xsp->mu);
}
...

The code fragment in the following example can be used when device operation completes, for example, in the device's interrupt handler.


Example 12–9 Device Operation Completion

...
/*
* For each command completion, decrement the busy count and unstack
* the pm_busy_component() call by calling pm_idle_component(). This
* will allow device power to be lowered when all commands complete
* (all pm_busy_component() counts are unstacked)
*/
xsp->xx_busy[component]--;
if (pm_idle_component(dip, component) != DDI_SUCCESS) {
xsp->xx_busy[component]++;
/*
* Log error and abort
*/
[...]
}

/*
* If no more outstanding commands, wake up anyone (like DDI_SUSPEND)
* waiting for all commands to be completed
*/
...

Power Management Flow of Control

Figure 12–1 illustrates the flow of control in the power management framework.

When a component's activity is complete, a driver can call pm_idle_component(9F) to mark the component as idle. When the component has been idle for its threshold time, the framework can lower the power of the component to its next lower level. The framework calls the power(9E) function to set the component's power to the next lower supported power level, if a lower level exists. The driver's power(9E) function should reject any attempt to lower the power level of a component when that component is busy. The power(9E) function should save any state that could be lost in a transition to a lower level prior to making that transition.

When the component is needed at a higher level, the driver calls pm_busy_component(9F). This call keeps the framework from lowering the power still further and then calls pm_raise_power(9F) on the component. The framework next calls power(9E) to raise the power of the component before the call to pm_raise_power(9F) returns. The driver's power(9E) code must restore any state that was lost in the lower level but that is needed in the higher level.

When a driver is detaching, the driver should call pm_lower_power(9F) for each component to lower its power to its lowest level. The framework can then call the driver's power(9E) routine to lower the power of the component before the call to pm_lower_power(9F) returns.

Figure 12–1 Power Management Conceptual State Diagram

Diagram shows the flow of control through power management
routines.

Changes to Power Management Interfaces

Prior to the Solaris 8 release, power management of devices was not automatic. Developers had to add an entry to /etc/power.conf for each device that was to be power-managed. The framework assumed that all devices supported only two power levels: 0 and standard power.

Power assumed an implied dependency of all other components on component 0. When component 0 changed to level 0, a call was made into the driver's detach(9E) with the DDI_PM_SUSPEND command to save the hardware state. When component 0 changed from level 0, a call was made to the attach(9E) routine with the command DDI_PM_RESUME to restore hardware state.

The following interfaces and commands are obsolete, although they are still supported for binary purposes:

  • ddi_dev_is_needed(9F)

  • pm_create_components(9F)

  • pm_destroy_components(9F)

  • pm_get_normal_power(9F)

  • pm_set_normal_power(9F)

  • DDI_PM_SUSPEND

  • DDI_PM_RESUME

Since the Solaris 8 release, devices that export the pm-components property automatically use power management if autopm is enabled.

The framework now knows from the pm-components property which power levels are supported by each device.

The framework makes no assumptions about dependencies among the different components of a device. The device driver is responsible for saving and restoring hardware state as needed when changing power levels.

These changes enable the power management framework to deal with emerging device technology. Power management now results in greater power savings. The framework can detect automatically which devices can save power. The framework can use intermediate power states of the devices. A system can now meet energy consumption goals without powering down the entire system and without any functions.

Table 12–1 Power Management Interfaces

Removed Interfaces 

Equivalent Interfaces 

pm_create_components(9F)

pm-components(9P)

pm_set_normal_power(9F)

pm-components(9P)

pm_destroy_components(9F)

None 

pm_get_normal_power(9F)

None 

ddi_dev_is_needed(9F)

pm_raise_power(9F)

None 

pm_lower_power(9F)

None 

pm_power_has_changed(9F)

DDI_PM_SUSPEND 

None 

DDI_PM_RESUME 

None 

 
【无人机】基于改进粒子群算法的无人机路径规划研究[和遗传算法、粒子群算法进行比较](Matlab代码实现)内容概要:本文围绕基于改进粒子群算法的无人机路径规划展开研究,重点探讨了在复杂环境中利用改进粒子群算法(PSO)实现无人机三维路径规划的方法,并将其与遗传算法(GA)、标准粒子群算法等传统优化算法进行对比分析。研究内容涵盖路径规划的多目标优化、避障策略、航路点约束以及算法收敛性和寻优能力的评估,所有实验均通过Matlab代码实现,提供了完整的仿真验证流程。文章还提到了多种智能优化算法在无人机路径规划中的应用比较,突出了改进PSO在收敛速度和全局寻优方面的优势。; 适合人群:具备一定Matlab编程基础和优化算法知识的研究生、科研人员及从事无人机路径规划、智能优化算法研究的相关技术人员。; 使用场景及目标:①用于无人机在复杂地形或动态环境下的三维路径规划仿真研究;②比较不同智能优化算法(如PSO、GA、蚁群算法、RRT等)在路径规划中的性能差异;③为多目标优化问题提供算法选型和改进思路。; 阅读建议:建议读者结合文中提供的Matlab代码进行实践操作,重点关注算法的参数设置、适应度函数设计及路径约束处理方式,同时可参考文中提到的多种算法对比思路,拓展到其他智能优化算法的研究与改进中。
<think>我们正在处理用户关于编译过程中遇到“No spaceleft ondevice”错误的问题。这个错误通常意味着磁盘空间不足,导致无法写入生成的汇编文件。我们需要提供解决此问题的方法。解决方案步骤:1.确认磁盘空间不足:使用系统命令检查磁盘使用情况。2.清理磁盘空间:删除不必要的文件,如临时文件、缓存、旧的日志文件等。3.扩大磁盘空间(如果需要):如果清理后空间仍然不足,考虑增加磁盘空间(如扩展磁盘分区或使用外部存储)。4.更改编译输出目录:如果可能,将编译输出定向到有足够空间的磁盘分区。我们将详细说明每一步的操作。注意:以下命令在Linux系统中常用,如果用户使用的是其他操作系统,请相应调整。步骤1:检查磁盘空间使用以下命令检查磁盘空间: ```bashdf -h```这个命令会显示每个挂载点的磁盘使用情况,找出空间不足的分区。步骤2:清理磁盘空间根据步骤1中找到的空间不足的分区,进行清理。常见的清理方法包括: -删除临时文件:通常位于`/tmp`目录,可以使用`sudorm -rf /tmp/*`(注意:确保/tmp目录中没有重要文件)。 -清理包管理器的缓存:对于基于Debian的系统(如Ubuntu),使用`sudo apt-getclean`;对于基于RedHat的系统(如Fedora、CentOS),使用`sudoyum cleanall`或`sudodnfclean all`。-删除旧的日志文件:可以删除`/var/log`目录下的旧日志文件,使用`sudo journalctl --vacuum-size=100M`(清理journal日志)或手动删除日志文件(注意:有些日志文件可能很重要,删除前请确认)。 -查找大文件并删除:使用`sudofind/ -typef -size +100M-execls -lh {}\; |sort -k5 -hr`查找大于100MB的文件,然后评估是否可以删除。步骤3:扩大磁盘空间(可选)如果清理后空间仍然不足,可以考虑:-扩展磁盘分区(如果使用虚拟机或物理机且有未分配空间)。 -挂载新的磁盘分区。 -使用云存储或外部存储。步骤4:更改编译输出目录如果另一个分区有足够的空间,可以将编译输出目录更改到该分区。例如,在编译时指定输出目录: ```bashmake -o/path/to/space_sufficient/directory```或者,如果是在使用cmake,可以在配置时指定输出目录: ```bashcmake-B/path/to/space_sufficient/directory```另外,如果用户正在使用Docker等容器,可能需要检查容器内的磁盘空间,或者将输出目录映射到宿主机上有足够空间的目录。注意事项:-在删除文件前,请确保文件不再需要,以免造成数据丢失。 -清理系统文件时,最好先备份重要数据。如果以上步骤不能解决问题,可能需要进一步分析系统日志或编译日志。生成相关问题:1.如何检查Linux系统中各个目录的磁盘使用情况?2.有哪些安全的方法可以清理Ubuntu系统的磁盘空间?3.如何扩展Linux系统的磁盘分区?4.在编译大型项目时,如何避免磁盘空间不足的问题?5.如何将编译输出重定向到另一个磁盘分区?我们提供了解决“No spaceleft ondevice”错误的基本步骤,用户可以根据具体情况选择操作。</think>### 解决“Error while writing generated assembler file: No space left on device”错误 此错误表明磁盘空间不足,导致编译器无法生成汇编文件。以下是系统性的解决方案: #### 1. **确认磁盘空间状态** ```bash df -h # 查看磁盘分区使用情况 du -sh /path/to/build_dir # 检查编译目录大小 ``` 重点关注`/tmp`、`/var`和项目目录所在分区的剩余空间。 #### 2. **立即释放空间** - **清理临时文件**: ```bash sudo rm -rf /tmp/* # 清除系统临时文件 rm -rf ~/.cache/* # 清除用户缓存 ``` - **删除旧编译产物**: ```bash make clean # 清理项目构建缓存 rm -rf build/ # 删除整个构建目录 ``` - **清理包管理器缓存**: ```apt sudo apt clean # Debian/Ubuntu sudo dnf clean all # Fedora/CentOS ``` #### 3. **定位大文件** ```bash sudo du -h / | grep '[0-9]G\b' # 查找大于1GB的文件 find / -type f -size +500M -exec ls -lh {} \; # 查找>500MB文件 ``` #### 4. **扩展可用空间** - **挂载新存储**: ```bash mkdir /mnt/build_space mount /dev/sdX1 /mnt/build_space # 挂载新磁盘 export TMPDIR=/mnt/build_space # 重定向临时目录 ``` - **调整编译输出路径**: ```bash ./configure --prefix=/mnt/build_space # 配置新安装路径 make -C /mnt/build_space # 指定构建目录 ``` #### 5. **优化编译过程** - **减少中间文件**: ```bash make -j4 # 限制并行编译进程数 strip binaries # 移除调试符号 ``` - **使用符号链接**: ```bash ln -s /mnt/space/tmp /project/tmp # 将临时目录链接到大空间分区 ``` #### 6. **预防措施** ```bash # 添加磁盘监控到cron */10 * * * * df -h | mail -s "Disk Report" admin@example.com # 设置编译自动清理 alias make='make && make clean-objs' ``` > **关键提示**: > - Docker用户需检查容器卷空间:`docker system prune -af` > - 云环境可动态扩展磁盘:AWS EBS/GCP Persistent Disk > - 持续集成环境中设置构建后自动清理[^1]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值