linux driver power

p { margin-bottom: 0.08in; }

static int __init pm_init( void )

{

power_kobj = kobject_create_and_add( "power" , NULL);

if (!power_kobj)

return -ENOMEM;

return sysfs_create_group(power_kobj, &attr_group);

}


core_initcall(pm_init);


static struct attribute_group attr_group = {

.attrs = g,

};


static struct attribute * g[] = {

&state_attr. attr , // 提供 给上面的一个接口

#ifdef CONFIG_PM_TRACE

&pm_trace_attr.attr,

#endif

#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PM_DEBUG)

&pm_test_attr.attr, //

#endif

NULL,

};

cat /sys/power 下就会显示 disk image_size pm_test pm_trace resume state

state 下面就会显示 mem,disk 这两种状态

cat /pm_trace 下面就会显示 1 或者 0

state 下面 mem,disk 的显示 是在以下函数功能实现的

static ssize_t state_show ( struct kobject *kobj, struct kobj_attribute *attr,

char *buf)

{

char *s = buf;

#ifdef CONFIG_SUSPEND

int i;


for (i = 0; i < PM_SUSPEND_MAX; i++) {

if (pm_states[i] && valid_state(i))

s += sprintf(s, "%s " , pm_states[i]);

}

#endif

#ifdef CONFIG_HIBERNATION

s += sprintf(s, "%s/n" , "disk" );

#else

if (s != buf)

/* convert the last space to a newline */

*(s-1) = '/n' ;

#endif

return (s - buf);

}

state 下面的更改 是在以下函数功能实现的

static ssize_t state_store ( struct kobject *kobj, struct kobj_attribute *attr,

const char *buf, size_t n)

{

#ifdef CONFIG_SUSPEND

suspend_state_t state = PM_SUSPEND_STANDBY;

const char * const *s;

#endif

char *p;

int len;

int error = -EINVAL;


p = memchr(buf, '/n' , n);

len = p ? p - buf : n;


/* First, check if we are requested to hibernate */

if (len == 4 && !strncmp(buf, "disk" , len)) { // 这里检测是进入硬盘还是 mm, 由于 6410 没有使用 disk ,所以就进入没有

error = hibernate();

goto Exit;

}


pm_trace 下面就会显示 1 或者 0 ,是在以下函数功能实现的

static ssize_t pm_trace_show( struct kobject *kobj, struct kobj_attribute *attr,

char *buf)

{

return sprintf(buf, "%d/n" , pm_trace_enabled);

}

pm_trace 状态的更改,是在以下函数功能实现的

pm_trace_store( struct kobject *kobj, struct kobj_attribute *attr,

const char *buf, size_t n)

{

int val;


if (sscanf(buf, "%d" , &val) == 1) {

pm_trace_enabled = !!val;

return n;

}

return -EINVAL;

}



# echo mem > /sys/power/state


1. 驱动在收到这个数据时就调用 state_store 函数来处理输入的状态,函数首先检查是否进

Hibernation 状态;如果 Hibernation 状态,那么就会调用 hibernate() 函数进入

Hibernation 状态,如果不是就找到要进入的状态,并调用 suspend enter_state 函数进

suspend 状态。我们看到在驱动的实现上把 Suspend Hibernation 区分开了。因此

Linux PM Suspend State 就有两个, standby mem 。注意这里没有 on ,因此你不能

通过发送 on 命来到 /sys/power/state 或其他内核接口函数来唤醒系统,因为这是针对服务

/PC 的,只能通过按键的方式(大多数的 PC/ 笔记本都提供了 Suspend 键,也可能就是

Power 键)。

suspend_state_t state = PM_SUSPEND_STANDBY;

if (len == 4 && !strncmp(buf, "disk", len)) {

error = hibernate();

}

if (state < PM_SUSPEND_MAX && *s)

error = enter_state(state);


enter_state suspend.c 里定义的接口函数,用来使系统进入指定的 suspend 状态。好了,

剩下的事情就交给 Suspend 系统来处理了。

2. 接下来调用会调用到 linux /kernel/power/mani.c 中的 enter_stare();

enter_state() 函数会进入和退出 suspend 状态时的一些常规处理,其过程是:

1). 调用 sys_sync();

同步文件系统以保证所有的数据都写到了存储设备上而不会因为 suspend 而丢失数据

2). 调用 suspend_prepare();

当进入到 suspend_prepare() 中以后,它使用 pm_prepare_console() 函数给 suspend

分配一个虚拟终端来输出信息 , 然后调用 pm_notifier_call_chain(PM_SUNPEND_PREPARE)

广播 一个系统要进入 suspend notify, 使用 usermodehelper_disable() 用户态的 helper , 调用 suspend_freeze_processes() 结所有的用户进 , 在这里也会

存当前进程的所有状态 .

3). 调用 suspend_devices_and_enter(state); 进入指定的 suspend 状态 ; 调用 device_suspend(

PMSG_SUSPEND); 跳到 linux/kernel/drivers/base/power/mani.c 中的 device_suspend(); 会调

dpm_prepare(); 然后再调用 dpm_suspend(); 调用 disable_noboot_cpus() 关闭非启动

cpu. 通过调用 suspend_device();

4). 接下来 suspend_enter() 会被调用, arch_suspend_disabled(); 然后

device_power_down(PMSG_SUSPEND); 会调用 suspend_device_noirq(); 最后调用

sysdev_suspend()

5).supend_ops->enter 来使 cpu 进入到 sleep 式;

在内核中的 /driver/base/core.c 中的 struct device 中的成员是在 /include/linux/device.h

struct device {

struct klist klist_children ;

struct klist_node knode_parent ; /* node in sibling list */

struct klist_node knode_driver ;

struct klist_node knode_bus ;

struct device * parent ;


struct kobject kobj ;

char bus_id [BUS_ID_SIZE]; /* position on parent bus */

const char * init_name ; /* initial name of the device */

struct device_type * type ;

unsigned uevent_suppress :1;


struct semaphore sem ; /* semaphore to synchronize calls to

* its driver.

*/


struct bus_type * bus ; /* type of bus device is on */

struct device_driver * driver ; /* which driver has allocated this

device */

void * driver_data ; /* data private to the driver */

void * platform_data ; /* Platform specific data, device

core doesn't touch it */

struct dev_pm_info power ; 这个很重要进入它的结构可以看到如下信息:


/include/linux/pm.h 中可以看到 如下 : enum dpm_state {

DPM_INVALID ,

DPM_ON ,

DPM_PREPARING ,

DPM_RESUMING ,

DPM_SUSPENDING ,

DPM_OFF ,

DPM_OFF_IRQ ,

};


struct dev_pm_info {

pm_message_t power_state ;

unsigned can_wakeup :1;

unsigned should_wakeup :1;

enum dpm_state status ; /* Owned by the PM core */

#ifdef CONFIG_PM_SLEEP

struct list_head entry;

#endif

};

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值