午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

linux驅(qū)動(dòng)程序之電源管理之標(biāo)準(zhǔn)linux休眠和喚醒機(jī)制分析(二)

 jiffes 2016-01-07

三、pm_test屬性文件讀寫

int pm_test_level = TEST_NONE;

 

static const char * const  pm_tests[__TEST_AFTER_LAST] = {

       [TEST_NONE] = "none",

       [TEST_CORE] = "core",

       [TEST_CPUS] = "processors",

       [TEST_PLATFORM] = "platform",

       [TEST_DEVICES] = "devices",

       [TEST_FREEZER] = "freezer",

};

// core >> processors >> platform >> devices >> freezer, 控制范圍示意

cat pm_test的時(shí)候最終會調(diào)用函數(shù)pm_test_show(),在終端上打印出上面數(shù)組中的字符串,當(dāng)前的模式用[]表示出來。

echo devices > pm_test的時(shí)候會最終調(diào)用到函數(shù)pm_test_store()中去,該函數(shù)中設(shè)置全局變量pm_test_level的值,可以是0-5,分別代表上none ~ freezer。該全局變量會在后面的suspend和resume中被引用到。

memchr函數(shù)說明:

原型:extern void *memchr(void *buf, char ch, unsigned int count);

用法:#include <string.h>   

功能:從buf所指內(nèi)存區(qū)域的前count個(gè)字節(jié)查找字符ch。   

說明:當(dāng)?shù)谝淮斡龅阶址鹀h時(shí)停止查找。如果成功,返回指向字符ch的指針;否則返回NULL。

 

四、state屬性文件

power_attr(state)宏定義了一個(gè)struct kobj_attribute結(jié)構(gòu)體state_attr:

static struct kobj_attribute state_attr = {  

       .attr = {

              .name = __stringify(state),

              .mode = 0644,      

       },

       .show     = state_show,

       .store      = state_store,

}

kobj_attribute結(jié)構(gòu)體封裝了struct attribute結(jié)構(gòu)體,新建屬性文件是依據(jù)struct attribute結(jié)構(gòu)體。最終通過函數(shù)kobj_attr_show和kobj_attr_store回調(diào)到實(shí)際的show和store函數(shù)(kobject.c)。

 

state_show()函數(shù)主要是顯示當(dāng)前系統(tǒng)支持哪幾種省電模式。

static ssize_t state_show(struct kobject *kobj,  struct kobj_attribute *attr,  char *buf)

{

       char *s = buf;

#ifdef CONFIG_SUSPEND  //def

       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       // undef, don't support STD mode

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

#else

       if (s != buf)

              /* convert the last space to a newline */

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

#endif

       return (s - buf);

}

 

@ kernel/include/linux/suspend.h

#define PM_SUSPEND_ON              ((__force suspend_state_t) 0)

#define PM_SUSPEND_STANDBY  ((__force suspend_state_t) 1)

#define PM_SUSPEND_MEM           ((__force suspend_state_t) 3)

#define PM_SUSPEND_DISK           ((__force suspend_state_t) 4)

#define PM_SUSPEND_MAX           ((__force suspend_state_t) 5)

 

@ kernel/kernel/power/suspend.c

const char *const pm_states[PM_SUSPEND_MAX] = {

#ifdef CONFIG_EARLYSUSPEND    // android修改了標(biāo)準(zhǔn)linux的休眠喚醒機(jī)制,增加了eraly suspend和late resume機(jī)制,如果是android內(nèi)核,則這個(gè)宏是需要定義的。

       [PM_SUSPEND_ON]          = "on",

#endif

       [PM_SUSPEND_STANDBY]     = "standby",

       [PM_SUSPEND_MEM]      = "mem",

};

該函數(shù)中值得注意的地方應(yīng)該是valid_state(i),這個(gè)函數(shù)是用戶配置的支持省電模式的驗(yàn)證函數(shù),如果沒有這個(gè)驗(yàn)證過程,cat時(shí)候打印出來的模式則是on standby mem,給上層用戶的使用造成困擾。

那這個(gè)valid_state()函數(shù)在哪里定義的呢?一般定義于文件kernel/kernel/power/suspend.c

static struct platform_suspend_ops   *suspend_ops;

void suspend_set_ops(struct platform_suspend_ops *ops) // 該函數(shù)調(diào)用見后面

{

       mutex_lock(&pm_mutex);

       suspend_ops = ops;

       mutex_unlock(&pm_mutex);

}

bool valid_state(suspend_state_t state)

{

       return suspend_ops && suspend_ops->valid && suspend_ops->valid(state);

}

 

而實(shí)際平臺的platform_suspend_ops結(jié)構(gòu)體一般都是在文件arch/arm/mach-xxxx/pm.c中進(jìn)行定義,對于mtk的平臺是文件mtkpm.c,如下:

@ kernel/include/linux/suspend.h

struct platform_suspend_ops {

       int (*valid)(suspend_state_t state);

       int (*begin)(suspend_state_t state);

       int (*prepare)(void);

       int (*prepare_late)(void);

       int (*enter)(suspend_state_t state);

       void (*wake)(void);

       void (*finish)(void);

       void (*end)(void);

       void (*recover)(void);

};

經(jīng)過后面的代碼分析,得出了如下結(jié)論:

休眠喚醒過程依次會執(zhí)行的函數(shù)是:begin,prepare,prepare_late,enter,wake, finish, end。同顏色的函數(shù)執(zhí)行了恰好相反的工作。休眠的時(shí)候代碼執(zhí)行是停留在函數(shù)enter中,wake之后也是從suspend的時(shí)候停留的地方繼續(xù)運(yùn)行。

至于recover函數(shù)貌似只有在pm_test處于devices的模式下,才會被調(diào)用到。

 

@ kernel/arch/arm/mach-mt6516/mtkpm.c

static struct platform_suspend_ops mtk_pm_ops = {

       .valid      = mtk_pm_state_valid,

       .begin            = mtk_pm_begin,

       .prepare  = mtk_pm_prepare,

       .enter            = mtk_pm_enter,

       .finish           = mtk_pm_finish,

       .end        = mtk_pm_end,

};

static int mtk_pm_state_valid(suspend_state_t pm_state)

{

    return pm_state == PM_SUSPEND_MEM ;

}

void mtk_pm_init(void)

{

       _Chip_PM_init();

    /* Register and set suspend operation */

    suspend_set_ops(&mtk_pm_ops);

}  

而函數(shù)mtk_pm_init()是在函數(shù)mt6516_init_irq()中調(diào)用??梢钥闯鲈撈脚_只支持mem的省電模式。

 

state_store()函數(shù):

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

                                         const char *buf, size_t n)

{

#ifdef CONFIG_SUSPEND // set

#ifdef CONFIG_EARLYSUSPEND    //對標(biāo)準(zhǔn)linux而言,這個(gè)宏不存在

       suspend_state_t state = PM_SUSPEND_ON;

#else

       suspend_state_t state = PM_SUSPEND_STANDBY;

#endif

       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)) {

              error = hibernate();       // 如果值是disk,那么進(jìn)入STD模式,該模式暫不討論

  goto Exit;

       }

 

#ifdef CONFIG_SUSPEND        // def

       for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {

              if (*s && len == strlen(*s) && !strncmp(buf, *s, len))

                     break;

       }

       if (state < PM_SUSPEND_MAX && *s)

#ifdef CONFIG_EARLYSUSPEND

// android的linux內(nèi)核會定義該宏,首先進(jìn)入eraly suspend模式

              if (state == PM_SUSPEND_ON || valid_state(state)) {

                     error = 0;

                     request_suspend_state(state);

              }

#else       // 標(biāo)準(zhǔn)linux內(nèi)核直接enter_state()函數(shù)

              error = enter_state(state);    // kernel/kernel/power/suspend.c

#endif

#endif

 

 Exit:

       return error ? error : n;

}

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多