日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

Linux电源管理(7)_Wakeup events framework

發(fā)布時(shí)間:2023/12/20 linux 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux电源管理(7)_Wakeup events framework 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. 前言

本文繼續(xù)“Linux電源管理(6)_Generic PM之Suspend功能”中有關(guān)suspend同步以及PM wakeup的話題。這個(gè)話題,是近幾年Linux kernel最具爭(zhēng)議的話題之一,在國(guó)外Linux開發(fā)論壇,經(jīng)常可以看到圍繞該話題的辯論。辯論的時(shí)間跨度和空間跨度可以持續(xù)很長(zhǎng),且無(wú)法達(dá)成一致。

wakeup events framework是這個(gè)話題的一個(gè)臨時(shí)性的解決方案,包括wake lock、wakeup count、autosleep等機(jī)制。它們就是本文的話題。

2. wakeup events framework要解決的問題

我們知道,系統(tǒng)處于suspend狀態(tài),可通過wakeup events喚醒。具體的wakeup events可以是按鍵按下,可以是充電器插入,等等。但是,如果在suspend的過程中,產(chǎn)生了wakeup events,怎么辦?答案很肯定,"wakeup"系統(tǒng)。由于此時(shí)系統(tǒng)沒有真正suspend,所以這的"wakeup"是個(gè)假動(dòng)作,實(shí)際上只是終止suspend。

但由于系統(tǒng)在suspend的過程中,會(huì)進(jìn)行process freeze、 device suspend等操作,而這些操作可能導(dǎo)致內(nèi)核或用戶空間程序不能及時(shí)獲取wakeup events,從而使系統(tǒng)不能正確wakeup,這就是wakeup events framework要解決的問題:system suspend和system wakeup events之間的同步問題。

3. wakeup events framework的功能總結(jié)

仔細(xì)推敲一下,上面所講的同步問題包括兩種情況:

情況1:內(nèi)核空間的同步

wakeup events產(chǎn)生后,通常是以中斷的形式通知device driver。driver會(huì)處理events,處理的過程中,系統(tǒng)不能suspend。

注1:同步問題只存在于中斷開啟的情況,因?yàn)槿糁袛嚓P(guān)閉,就不會(huì)產(chǎn)生wakeup events,也就不存在同步的概念。

情況2:用戶空間的同步

一般情況下,driver對(duì)wakeup events處理后,會(huì)交給用戶空間程序繼續(xù)處理,處理的過程,也不允許suspend。這又可以分為兩種情況:

1)進(jìn)行后續(xù)處理的用戶進(jìn)程,根本沒有機(jī)會(huì)被調(diào)度,即該wakeup events無(wú)法上報(bào)到用戶空間。

2)進(jìn)行后續(xù)處理的用戶進(jìn)程被調(diào)度,處理的過程中(以及處理結(jié)束后,決定終止suspend操作),系統(tǒng)不能suspend。

因此,wakeup events framework就包括3大功能:

解決內(nèi)核空間同步問題(framework的核心功能);

解決用戶空間同步問題的情景1(wakeup count功能);

解決用戶空間同步問題的情景2(wake lock功能) 。

注2:
用戶空間同步的兩種情況,咋一看,非常合乎情理,kernel你得好好處理!但事實(shí)上,該同步問題牽涉到了另外一個(gè)比較有爭(zhēng)議的話題:日常的電源管理機(jī)制。是否要基于suspend實(shí)現(xiàn)?系統(tǒng)何時(shí)進(jìn)入低功耗狀態(tài),應(yīng)該由誰(shuí)決定?kernel還是用戶空間程序?

這最終會(huì)決定是否存在用空間同步問題。但是,在當(dāng)前這個(gè)時(shí)間點(diǎn),對(duì)這個(gè)話題,Linux kernel developers和Android developers持相反的觀點(diǎn)。這也造成了wakeup events framework在實(shí)現(xiàn)上的撕裂。Kernel的本意是不愿處理用戶空間同步問題的,但為了兼容Android平臺(tái),不得不增加相關(guān)的功能(Wakeup count和Wake lock)。

蝸蝸會(huì)在下一篇文章和大家探討該話題,本文就先f(wàn)ocus在wakeup events framework上。

4. wakeup events framework architecture

下面圖片描述了wakeup events framework的architecture:

圖片中紅色邊框的block是wakeup events相關(guān)的block:

抽象wakeup source和wakeup event的概念;

向各個(gè)device driver提供wakeup source的注冊(cè)、使能等接口;

向各個(gè)device driver提供wakeup event的上報(bào)、停止等接口;

向上層的PM core(包括wakeup count、auto sleep、suspend、hibernate等模塊)提供wakeup event的查詢接口,以判斷是否可以suspend、是否需要終止正在進(jìn)行的suspend。

2)wakeup events framework sysfs,將設(shè)備的wakeup信息,以sysfs的形式提供到用戶空間,供用戶空間程序查詢、配置。在drivers/base/power/sysfs.c中實(shí)現(xiàn)。

3)wake lock/unlock,為了兼容Android舊的wakeup lock機(jī)制而留下的一個(gè)后門,擴(kuò)展wakeup events framework的功能,允許用戶空間程序報(bào)告/停止wakeup events。換句話說(shuō),該后門允許用戶空間的任一程序決定系統(tǒng)是否可以休眠。

4)wakeup count,基于wakeup events framework,解決用戶空間同步的問題。

5)auto sleep,允許系統(tǒng)在沒有活動(dòng)時(shí)(即一段時(shí)間內(nèi),沒有產(chǎn)生wakeup event),自動(dòng)休眠。

注3:在Linux kernel看來(lái),power是系統(tǒng)的核心資源,不應(yīng)開放給用戶程序隨意訪問(wake lock機(jī)制違背了這個(gè)原則)。而在運(yùn)行時(shí)的電源管理過程中,系統(tǒng)何時(shí)進(jìn)入低功耗狀態(tài),也不是用戶空間程序能決定的(auto sleep中槍了)。因此,kernel對(duì)上述功能的支持,非常的不樂意,我們可以從kernel/power/main.c中sysfs attribute文件窺見一斑(只要定義了PM_SLEEP,就一定支持wakeup count功能,但autosleep和wake lock功能,由另外的宏定義控制):

1: static struct attribute * g[] = {2: &state_attr.attr,3: #ifdef CONFIG_PM_TRACE4: &pm_trace_attr.attr,5: &pm_trace_dev_match_attr.attr,6: #endif7: #ifdef CONFIG_PM_SLEEP8: &pm_async_attr.attr,9: &wakeup_count_attr.attr,10: #ifdef CONFIG_PM_AUTOSLEEP11: &autosleep_attr.attr,12: #endif13: #ifdef CONFIG_PM_WAKELOCKS14: &wake_lock_attr.attr,15: &wake_unlock_attr.attr,16: #endif17: #ifdef CONFIG_PM_DEBUG18: &pm_test_attr.attr,19: #endif20: #ifdef CONFIG_PM_SLEEP_DEBUG21: &pm_print_times_attr.attr,22: #endif23: #endif24: #ifdef CONFIG_FREEZER25: &pm_freeze_timeout_attr.attr,26: #endif27: NULL,28: };

5. 代碼分析

5.1 wakeup source和wakeup event

在kernel中,可以喚醒系統(tǒng)的只有設(shè)備(struct device),但并不是每個(gè)設(shè)備都具備喚醒功能,那些具有喚醒功能的設(shè)備稱作wakeup source。是時(shí)候回到這篇文章中了(Linux設(shè)備模型(5)_device和device driver),在那里,介紹struct device結(jié)構(gòu)時(shí),涉及到一個(gè)struct dev_pm_info類型的power變量,蝸蝸說(shuō)留待后面的專題講解。我們?cè)倩貞浺幌聅truct device結(jié)構(gòu):

1: struct device {2: ...3: struct dev_pm_info power;4: ...5: };

該結(jié)構(gòu)中有一個(gè)power變量,保存了和wakeup event相關(guān)的信息,讓我們接著看一下struct dev_pm_info數(shù)據(jù)結(jié)構(gòu)(只保留和本文有關(guān)的內(nèi)容):

1: struct dev_pm_info {2: ...3: unsigned int can_wakeup:1;4: ...5: #ifdef CONFIG_PM_SLEEP6: ...7: struct wakeup_source *wakeup;8: ...9: #else10: unsigned int should_wakeup:1;11: #endif12: };

can_wakeup,標(biāo)識(shí)本設(shè)備是否具有喚醒能力。只有具備喚醒能力的設(shè)備,才會(huì)在sysfs中有一個(gè)power目錄,用于提供所有的wakeup信息,這些信息是以struct wakeup_source的形式組織起來(lái)的。也就是上面wakeup指針。具體有哪些信息呢?讓我們看看struct wakeup_source的定義。

1: /* include\linux\pm_wakeup.h */2: struct wakeup_source {3: const char *name;4: struct list_head entry;5: spinlock_t lock;6: struct timer_list timer;7: unsigned long timer_expires;8: ktime_t total_time;9: ktime_t max_time;10: ktime_t last_time;11: ktime_t start_prevent_time;12: ktime_t prevent_sleep_time;13: unsigned long event_count;14: unsigned long active_count;15: unsigned long relax_count;16: unsigned long expire_count;17: unsigned long wakeup_count;18: bool active:1;19: bool autosleep_enabled:1;20: };

因此,一個(gè)wakeup source代表了一個(gè)具有喚醒能力的設(shè)備,也稱該設(shè)備為一個(gè)wakeup source。該結(jié)構(gòu)中各個(gè)字段的意義如下:

name,該wakeup source的名稱,一般為對(duì)應(yīng)的device name(有個(gè)例外,就是wakelock);

entery,用于將所有的wakeup source掛在一個(gè)鏈表中;

timer、timer_expires,一個(gè)wakeup source產(chǎn)生了wakeup event,稱作wakeup source activate,wakeup event處理完畢后(不再需要系統(tǒng)為此保持active),稱作deactivate。activate和deactivate的操作可以由driver親自設(shè)置,也可以在activate時(shí),指定一個(gè)timeout時(shí)間,時(shí)間到達(dá)后,由wakeup events framework自動(dòng)將其設(shè)置為deactivate狀態(tài)。這里的timer以及expires時(shí)間,就是用來(lái)實(shí)現(xiàn)該功能;

total_time,該wakeup source處于activate狀態(tài)的總時(shí)間(可以指示該wakeup source對(duì)應(yīng)的設(shè)備的繁忙程度、耗電等級(jí));

max_time,該wakeup source持續(xù)處于activate狀態(tài)的最大時(shí)間(越長(zhǎng)越不合理);

last_time,該wakeup source上次active的開始時(shí)間;

start_prevent_time,該wakeup source開始阻止系統(tǒng)自動(dòng)睡眠(auto sleep)的時(shí)間點(diǎn);

prevent_sleep_time,該wakeup source阻止系統(tǒng)自動(dòng)睡眠的總時(shí)間;

event_count,wakeup source上報(bào)的event個(gè)數(shù);

active_count,wakeup source activate的次數(shù);

relax_count, wakeup source deactivate的次數(shù);

expire_count,wakeup source timeout到達(dá)的次數(shù);

wakeup_count,wakeup source終止suspend過程的次數(shù);

active,wakeup source的activate狀態(tài);

autosleep_enabled,記錄系統(tǒng)auto sleep的使能狀態(tài)(每個(gè)wakeup source都重復(fù)記錄這樣一個(gè)狀態(tài),這種設(shè)計(jì)真實(shí)不敢恭維!)

wakeup source代表一個(gè)具有喚醒能力的設(shè)備,該設(shè)備產(chǎn)生的可以喚醒系統(tǒng)的事件,就稱作wakeup event。當(dāng)wakeup source產(chǎn)生wakeup event時(shí),需要將wakeup source切換為activate狀態(tài);當(dāng)wakeup event處理完畢后,要切換為deactivate狀態(tài)。因此,我們?cè)賮?lái)理解一下幾個(gè)wakeup source比較混淆的變量:event_count, active_count和wakeup_count:

event_count,wakeup source產(chǎn)生的wakeup event的個(gè)數(shù);

active_count,產(chǎn)生wakeup event時(shí),wakeup source需要切換到activate狀態(tài)。但并不是每次都要切換,因此有可能已經(jīng)處于activate狀態(tài)了。因此active_count可能小于event_count,換句話說(shuō),很有可能在前一個(gè)wakeup event沒被處理完時(shí),又產(chǎn)生了一個(gè)。這從一定程度上反映了wakeup source所代表的設(shè)備的繁忙程度;

wakeup_count,wakeup source在suspend過程中產(chǎn)生wakeup event的話,就會(huì)終止suspend過程,該變量記錄了wakeup source終止suspend過程的次數(shù)(如果發(fā)現(xiàn)系統(tǒng)總是suspend失敗,檢查一下各個(gè)wakeup source的該變量,就可以知道問題出在誰(shuí)身上了)。

5.2 幾個(gè)counters

在drivers\base\power\wakeup.c中,有幾個(gè)比較重要的計(jì)數(shù)器,是wakeup events framework的實(shí)現(xiàn)基礎(chǔ),包括:

1)registered wakeup events和saved_count

記錄了系統(tǒng)運(yùn)行以來(lái)產(chǎn)生的所有wakeup event的個(gè)數(shù),在wakeup source上報(bào)event時(shí)加1。

這個(gè)counter對(duì)解決用戶空間同步問題很有幫助,因?yàn)橐话闱闆r下(無(wú)論是用戶程序主動(dòng)suspend,還是auto sleep),由專門的進(jìn)程(或線程)觸發(fā)suspend。當(dāng)這個(gè)進(jìn)程判斷系統(tǒng)滿足suspend條件,決定suspend時(shí),會(huì)記錄一個(gè)counter值(saved_count)。在后面suspend的過程中,如果系統(tǒng)發(fā)現(xiàn)counter有變,則說(shuō)明系統(tǒng)產(chǎn)生了新的wakeup event,這樣就可以終止suspend。

該功能即是wakeup count功能,會(huì)在后面更詳細(xì)的說(shuō)明。

2)wakeup events in progress

記錄正在處理的event個(gè)數(shù)。

當(dāng)wakeup source產(chǎn)生wakeup event時(shí),會(huì)通過wakeup events framework提供的接口將wakeup source設(shè)置為activate狀態(tài)。當(dāng)該event處理結(jié)束后,設(shè)置為deactivate狀態(tài)。activate到deactivate的區(qū)間,表示該event正在被處理。

當(dāng)系統(tǒng)中有任何正在被處理的wakeup event時(shí),則不允許suspend。如果suspend正在進(jìn)行,則要終止。

思考一個(gè)問題:registered wakeup events在什么時(shí)候增加?答案是在wakeup events in progress減小時(shí),因?yàn)橐呀?jīng)完整的處理完一個(gè)event了,可以記錄在案了。

1: /*2: * Combined counters of registered wakeup events and wakeup events in progress.3: * They need to be modified together atomically, so it's better to use one4: * atomic variable to hold them both.5: */6: static atomic_t combined_event_count = ATOMIC_INIT(0);7: 8: #define IN_PROGRESS_BITS (sizeof(int) * 4)9: #define MAX_IN_PROGRESS ((1 << IN_PROGRESS_BITS) - 1)10: 11: static void split_counters(unsigned int *cnt, unsigned int *inpr)12: {13: unsigned int comb = atomic_read(&combined_event_count);14: 15: *cnt = (comb >> IN_PROGRESS_BITS);16: *inpr = comb & MAX_IN_PROGRESS;17: }

定義和讀取。

1: cec = atomic_add_return(MAX_IN_PROGRESS, &combined_event_count);

wakeup events in progress減1,registered wakeup events加1,這個(gè)語(yǔ)句簡(jiǎn)直是美輪美奐,讀者可以仔細(xì)品味一下,絕對(duì)比看xxx片還過癮,哈哈。

1: cec = atomic_inc_return(&combined_event_count);

wakeup events in progress加1。

5.3 wakeup events framework的核心功能

wakeup events framework的核心功能體現(xiàn)在它向底層的設(shè)備驅(qū)動(dòng)所提供的用于上報(bào)wakeup event的接口,這些接口根據(jù)操作對(duì)象可分為兩類,具體如下。

類型一(操作對(duì)象為wakeup source,編寫設(shè)備驅(qū)動(dòng)時(shí),一般不會(huì)直接使用):

1: /* include/linux/pm_wakeup.h */2: extern void __pm_stay_awake(struct wakeup_source *ws);3: extern void __pm_relax(struct wakeup_source *ws);4: extern void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec);

__pm_stay_awake,通知PM core,ws產(chǎn)生了wakeup event,且正在處理,因此不允許系統(tǒng)suspend(stay awake);

__pm_relax,通知PM core,ws沒有正在處理的wakeup event,允許系統(tǒng)suspend(relax);

__pm_wakeup_event,為上邊兩個(gè)接口的功能組合,通知PM core,ws產(chǎn)生了wakeup event,會(huì)在msec毫秒內(nèi)處理結(jié)束(wakeup events framework自動(dòng)relax)。

注4:__pm_stay_awake和__pm_relax應(yīng)成對(duì)調(diào)用。
注5:上面3個(gè)接口,均可以在中斷上下文調(diào)用。

類型二(操作對(duì)象為device,為設(shè)備驅(qū)動(dòng)的常用接口):

1: /* include/linux/pm_wakeup.h */2: extern int device_wakeup_enable(struct device *dev);3: extern int device_wakeup_disable(struct device *dev);4: extern void device_set_wakeup_capable(struct device *dev, bool capable);5: extern int device_init_wakeup(struct device *dev, bool val);6: extern int device_set_wakeup_enable(struct device *dev, bool enable);7: extern void pm_stay_awake(struct device *dev);8: extern void pm_relax(struct device *dev);9: extern void pm_wakeup_event(struct device *dev, unsigned int msec);

device_set_wakeup_capable,設(shè)置dev的can_wakeup標(biāo)志(enable或disable,可參考5.1小節(jié)),并增加或移除該設(shè)備在sysfs相關(guān)的power文件;

device_wakeup_enable/device_wakeup_disable/device_set_wakeup_enable,對(duì)于can_wakeup的設(shè)備,使能或者禁止wakeup功能。主要是對(duì)struct wakeup_source結(jié)構(gòu)的相關(guān)操作;

device_init_wakeup,設(shè)置dev的can_wakeup標(biāo)志,若是enable,同時(shí)調(diào)用device_wakeup_enable使能wakeup功能;

pm_stay_awake、pm_relax、pm_wakeup_event,直接調(diào)用上面的wakeup source操作接口,操作device的struct wakeup_source變量,處理wakeup events。

5.3.1 device_set_wakeup_capable

該接口位于在drivers/base/power/wakeup.c中,代碼如下:

1: void device_set_wakeup_capable(struct device *dev, bool capable)2: {3: if (!!dev->power.can_wakeup == !!capable)4: return;5: 6: if (device_is_registered(dev) && !list_empty(&dev->power.entry)) {7: if (capable) {8: if (wakeup_sysfs_add(dev))9: return;10: } else {11: wakeup_sysfs_remove(dev);12: }13: }14: dev->power.can_wakeup = capable;15: }

該接口的實(shí)現(xiàn)很簡(jiǎn)單,主要包括sysfs的add/remove和can_wakeup標(biāo)志的設(shè)置兩部分。如果設(shè)置can_wakeup標(biāo)志,則調(diào)用wakeup_sysfs_add,向該設(shè)備的sysfs目錄下添加power文件夾,并注冊(cè)相應(yīng)的attribute文件。如果清除can_wakeup標(biāo)志,執(zhí)行sysfs的移除操作。

wakeup_sysfs_add/wakeup_sysfs_remove位于drivers/base/power/sysfs.c中,對(duì)wakeup events framework來(lái)說(shuō),主要包括如下的attribute文件:

1: static struct attribute *wakeup_attrs[] = {2: #ifdef CONFIG_PM_SLEEP3: &dev_attr_wakeup.attr,4: &dev_attr_wakeup_count.attr,5: &dev_attr_wakeup_active_count.attr,6: &dev_attr_wakeup_abort_count.attr,7: &dev_attr_wakeup_expire_count.attr,8: &dev_attr_wakeup_active.attr,9: &dev_attr_wakeup_total_time_ms.attr,10: &dev_attr_wakeup_max_time_ms.attr,11: &dev_attr_wakeup_last_time_ms.attr,12: #ifdef CONFIG_PM_AUTOSLEEP13: &dev_attr_wakeup_prevent_sleep_time_ms.attr,14: #endif15: #endif16: NULL,17: };18: static struct attribute_group pm_wakeup_attr_group = {19: .name = power_group_name,20: .attrs = wakeup_attrs,21: }; 1: static struct attribute *wakeup_attrs[] = {2: #ifdef CONFIG_PM_SLEEP3: &dev_attr_wakeup.attr,4: &dev_attr_wakeup_count.attr,5: &dev_attr_wakeup_active_count.attr,6: &dev_attr_wakeup_abort_count.attr,7: &dev_attr_wakeup_expire_count.attr,8: &dev_attr_wakeup_active.attr,9: &dev_attr_wakeup_total_time_ms.attr,10: &dev_attr_wakeup_max_time_ms.attr,11: &dev_attr_wakeup_last_time_ms.attr,12: #ifdef CONFIG_PM_AUTOSLEEP13: &dev_attr_wakeup_prevent_sleep_time_ms.attr,14: #endif15: #endif16: NULL,17: };18: static struct attribute_group pm_wakeup_attr_group = {19: .name = power_group_name,20: .attrs = wakeup_attrs,21: };

1)wakeup

讀,獲得設(shè)備wakeup功能的使能狀態(tài),返回"enabled"或"disabled"字符串。

寫,更改設(shè)備wakeup功能的使能狀態(tài),根據(jù)寫入的字符串("enabled"或"disabled"),調(diào)用device_set_wakeup_enable接口完成實(shí)際的狀態(tài)切換。

設(shè)備wakeup功能是否使能,取決于設(shè)備的can_wakeup標(biāo)志,以及設(shè)備是否注冊(cè)有相應(yīng)的struct wakeup_source指針。即can wakeup和may wakeup,如下:

1: /*2: * Changes to device_may_wakeup take effect on the next pm state change.3: */4: 5: static inline bool device_can_wakeup(struct device *dev)6: {7: return dev->power.can_wakeup;8: }9: 10: static inline bool device_may_wakeup(struct device *dev)11: {12: return dev->power.can_wakeup && !!dev->power.wakeup;13: }

2)wakeup_count

只讀,獲取dev->power.wakeup->event_count值。有關(guān)event_count的意義,請(qǐng)參考5.1小節(jié),下同。順便抱怨一下,這個(gè)attribute文件的命名簡(jiǎn)直糟糕透頂了!直接用event_count就是了,用什么wakeup_count,會(huì)和wakeup source中的同名字段搞混淆的!

3)wakeup_active_count,只讀,獲取dev->power.wakeup->active_count值。

4)wakeup_abort_count,只讀,獲取dev->power.wakeup->wakeup_count值。

5)wakeup_expire_count,只讀,獲dev->power.wakeup->expire_count取值。

6)wakeup_active,只讀,獲取dev->power.wakeup->active值。

7)wakeup_total_time_ms,只讀,獲取dev->power.wakeup->total_time值,單位為ms。

8)wakeup_max_time_ms,只讀,獲dev->power.wakeup->max_time取值,單位為ms。

9)wakeup_last_time_ms,只讀,獲dev->power.wakeup->last_time取值,單位為ms。

10)wakeup_prevent_sleep_time_ms,只讀,獲取dev->power.wakeup->prevent_sleep_time值,單位為ms。

注6:閱讀上述代碼時(shí),我們可以看到很多類似“!!dev->power.can_wakeup == !!capable”的、帶有兩個(gè)“!”操作符的語(yǔ)句,是為了保證最后的操作對(duì)象非0即1。這從側(cè)面反映了內(nèi)核開發(fā)者的嚴(yán)謹(jǐn)程度,值得我們學(xué)習(xí)。

5.3.2 device_wakeup_enable/device_wakeup_disable/device_set_wakeup_enable

以device_wakeup_enable為例(其它類似,就不浪費(fèi)屏幕了):

1: int device_wakeup_enable(struct device *dev)2: {3: struct wakeup_source *ws;4: int ret;5: 6: if (!dev || !dev->power.can_wakeup)7: return -EINVAL;8: 9: ws = wakeup_source_register(dev_name(dev));10: if (!ws)11: return -ENOMEM;12: 13: ret = device_wakeup_attach(dev, ws);14: if (ret)15: wakeup_source_unregister(ws);16: 17: return ret;18: }

也很簡(jiǎn)單:

a)若設(shè)備指針為空,或者設(shè)備不具備wakeup能力,免談,報(bào)錯(cuò)退出。

b)調(diào)用wakeup_source_register接口,以設(shè)備名為參數(shù),創(chuàng)建并注冊(cè)一個(gè)wakeup source。

c)調(diào)用device_wakeup_attach接口,將新建的wakeup source保存在dev->power.wakeup指針中。

wakeup_source_register接口的實(shí)現(xiàn)也比較簡(jiǎn)單,會(huì)先后調(diào)用wakeup_source_create、wakeup_source_prepare、wakeup_source_add等接口,所做的工作包括分配struct wakeup_source變量所需的內(nèi)存空間、初始化內(nèi)部變量、將新建的wakeup source添加到名稱為wakeup_sources的全局鏈表中、等等。

device_wakeup_attach接口更為直觀,不過有一點(diǎn)我們要關(guān)注,如果設(shè)備的dev->power.wakeup非空,也就是說(shuō)之前已經(jīng)有一個(gè)wakeup source了,是不允許再enable了的,會(huì)報(bào)錯(cuò)返回。

5.3.3 pm_stay_awake

當(dāng)設(shè)備有wakeup event正在處理時(shí),需要調(diào)用該接口通知PM core,該接口的實(shí)現(xiàn)如下:

1: void pm_stay_awake(struct device *dev)2: {3: unsigned long flags;4: 5: if (!dev)6: return;7: 8: spin_lock_irqsave(&dev->power.lock, flags);9: __pm_stay_awake(dev->power.wakeup);10: spin_unlock_irqrestore(&dev->power.lock, flags);11: }

呵呵,直接調(diào)用__pm_stay_awake,這也是本文的index里沒有該接口的原因。接著看代碼。

1: void __pm_stay_awake(struct wakeup_source *ws)2: {3: unsigned long flags;4: 5: if (!ws)6: return;7: 8: spin_lock_irqsave(&ws->lock, flags);9: 10: wakeup_source_report_event(ws);11: del_timer(&ws->timer);12: ws->timer_expires = 0;13: 14: spin_unlock_irqrestore(&ws->lock, flags);15: }

由于pm_stay_awake報(bào)告的event需要經(jīng)過pm_relax主動(dòng)停止,因此就不再需要timer,所以__pm_stay_awake實(shí)現(xiàn)是直接調(diào)用wakeup_source_report_event,然后停止timer。接著看代碼:

1: static void wakeup_source_report_event(struct wakeup_source *ws)2: {3: ws->event_count++;4: /* This is racy, but the counter is approximate anyway. */5: if (events_check_enabled)6: ws->wakeup_count++;7: 8: if (!ws->active)9: wakeup_source_activate(ws);10: }

a)增加wakeup source的event_count,表示該source又產(chǎn)生了一個(gè)event。

b)根據(jù)events_check_enabled變量的狀態(tài),決定是否增加wakeup_count。這和wakeup count的功能有關(guān),到時(shí)再詳細(xì)描述。

c)如果wakeup source沒有active,則調(diào)用wakeup_source_activate,activate之。這也是5.1小節(jié)所描述的,event_count和active_count的區(qū)別所在。wakeup_source_activate的代碼如下。

1: static void wakeup_source_activate(struct wakeup_source *ws)2: {3: unsigned int cec;4: 5: /*6: * active wakeup source should bring the system7: * out of PM_SUSPEND_FREEZE state8: */9: freeze_wake();10: 11: ws->active = true;12: ws->active_count++;13: ws->last_time = ktime_get();14: if (ws->autosleep_enabled)15: ws->start_prevent_time = ws->last_time;16: 17: /* Increment the counter of events in progress. */18: cec = atomic_inc_return(&combined_event_count);19: 20: trace_wakeup_source_activate(ws->name, cec);21: }

a)調(diào)用freeze_wake,將系統(tǒng)從suspend to freeze狀態(tài)下喚醒。有關(guān)freeze功能,請(qǐng)參考相關(guān)的文章。

b)設(shè)置active標(biāo)志,增加active_count,更新last_time。

c)如果使能了autosleep,更新start_prevent_time,因?yàn)榇丝淘搘akeup source會(huì)開始阻止系統(tǒng)auto sleep。具體可參考auto sleep的功能描述。

d)增加“wakeup events in progress”計(jì)數(shù)(5.2小節(jié)有描述)。該操作是wakeup events framework的靈魂,增加該計(jì)數(shù),意味著系統(tǒng)正在處理的wakeup event數(shù)目不為零,則系統(tǒng)不能suspend。

到此,pm_stay_awake執(zhí)行結(jié)束,意味著系統(tǒng)至少正在處理一個(gè)wakeup event,因此不能suspend。那處理完成后呢?driver要調(diào)用pm_relax通知PM core。

5.3.4 pm_relax

pm_relax和pm_stay_awake成對(duì)出現(xiàn),用于在event處理結(jié)束后通知PM core,其實(shí)現(xiàn)如下:

1: /**2: * pm_relax - Notify the PM core that processing of a wakeup event has ended.3: * @dev: Device that signaled the event.4: *5: * Execute __pm_relax() for the @dev's wakeup source object.6: */7: void pm_relax(struct device *dev)8: {9: unsigned long flags;10: 11: if (!dev)12: return;13: 14: spin_lock_irqsave(&dev->power.lock, flags);15: __pm_relax(dev->power.wakeup);16: spin_unlock_irqrestore(&dev->power.lock, flags);17: }

直接調(diào)用__pm_relax,如下:

1: void __pm_relax(struct wakeup_source *ws)2: {3: unsigned long flags;4: 5: if (!ws)6: return;7: 8: spin_lock_irqsave(&ws->lock, flags);9: if (ws->active)10: wakeup_source_deactivate(ws);11: spin_unlock_irqrestore(&ws->lock, flags);12: }

如果該wakeup source處于active狀態(tài),調(diào)用wakeup_source_deactivate接口,deactivate之。deactivate接口和activate接口一樣,是wakeup events framework的核心邏輯,如下:

1: static void wakeup_source_deactivate(struct wakeup_source *ws)2: {3: unsigned int cnt, inpr, cec;4: ktime_t duration;5: ktime_t now;6: 7: ws->relax_count++;8: /*9: * __pm_relax() may be called directly or from a timer function.10: * If it is called directly right after the timer function has been11: * started, but before the timer function calls __pm_relax(), it is12: * possible that __pm_stay_awake() will be called in the meantime and13: * will set ws->active. Then, ws->active may be cleared immediately14: * by the __pm_relax() called from the timer function, but in such a15: * case ws->relax_count will be different from ws->active_count.16: */17: if (ws->relax_count != ws->active_count) {18: ws->relax_count--;19: return;20: }21: 22: ws->active = false;23: 24: now = ktime_get();25: duration = ktime_sub(now, ws->last_time);26: ws->total_time = ktime_add(ws->total_time, duration);27: if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time))28: ws->max_time = duration;29: 30: ws->last_time = now;31: del_timer(&ws->timer);32: ws->timer_expires = 0;33: 34: if (ws->autosleep_enabled)35: update_prevent_sleep_time(ws, now);36: 37: /*38: * Increment the counter of registered wakeup events and decrement the39: * couter of wakeup events in progress simultaneously.40: */41: cec = atomic_add_return(MAX_IN_PROGRESS, &combined_event_count);42: trace_wakeup_source_deactivate(ws->name, cec);43: 44: 45: split_counters(&cnt, &inpr);46: if (!inpr && waitqueue_active(&wakeup_count_wait_queue))47: wake_up(&wakeup_count_wait_queue);48: }

a)relax_count加1(如果relax_count和active_count不等,則說(shuō)明有重復(fù)調(diào)用,要退出)。

b)清除active標(biāo)記。

c)更新total_time、max_time、last_time等變量。

d)如果使能auto sleep,更新相關(guān)的變量(后面再詳細(xì)描述)。

e)再欣賞一下藝術(shù),wakeup events in progress減1,registered wakeup events加1。

f)wakeup count相關(guān)的處理,后面再詳細(xì)說(shuō)明。

5.3.5 pm_wakeup_event

pm_wakeup_event是pm_stay_awake和pm_relax的組合版,在上報(bào)event時(shí),指定一個(gè)timeout時(shí)間,timeout后,自動(dòng)relax,一般用于不知道何時(shí)能處理完成的場(chǎng)景。該接口比較簡(jiǎn)單,就不一一描述了。

5.3.6 pm_wakeup_pending

drivers產(chǎn)生的wakeup events,最終要上報(bào)到PM core,PM core會(huì)根據(jù)這些events,決定是否要終止suspend過程。這表現(xiàn)在suspend過程中頻繁調(diào)用pm_wakeup_pending接口上(可參考“Linux電源管理(6)_Generic PM之Suspend功能”)。該接口的實(shí)現(xiàn)如下:

1: /**2: * pm_wakeup_pending - Check if power transition in progress should be aborted.3: *4: * Compare the current number of registered wakeup events with its preserved5: * value from the past and return true if new wakeup events have been registered6: * since the old value was stored. Also return true if the current number of7: * wakeup events being processed is different from zero.8: */9: bool pm_wakeup_pending(void)10: {11: unsigned long flags;12: bool ret = false;13: 14: spin_lock_irqsave(&events_lock, flags);15: if (events_check_enabled) {16: unsigned int cnt, inpr;17: 18: split_counters(&cnt, &inpr);19: ret = (cnt != saved_count || inpr > 0);20: events_check_enabled = !ret;21: }22: spin_unlock_irqrestore(&events_lock, flags);23: 24: if (ret)25: print_active_wakeup_sources();26: 27: return ret;28: }

該接口的邏輯比較直觀,先拋開wakeup count的邏輯不談(后面會(huì)重點(diǎn)說(shuō)明),只要正在處理的events不為0,就返回true,調(diào)用者就會(huì)終止suspend。

5.4 wakeup count、wake lock和auto sleep

這篇文章寫的有點(diǎn)長(zhǎng)了,不能繼續(xù)了,這幾個(gè)功能,會(huì)接下來(lái)的文章中繼續(xù)分析。

總結(jié)

以上是生活随笔為你收集整理的Linux电源管理(7)_Wakeup events framework的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

亚洲日日日 | 欧美精品久久久久久久 | 亚洲午夜精品久久久久久久久久久久 | 日韩在线理论 | 97在线观看免费 | 91福利社区在线观看 | 片网站| 欧美一级xxxx | 日韩免费视频观看 | 久久国产乱 | 国产精品18久久久久久vr | 天天射天天操天天色 | 在线观看免费视频你懂的 | 国产成人在线一区 | 日韩av一区二区在线影视 | 亚洲日本三级 | 日韩美av在线| 黄色三级在线看 | 五月开心六月伊人色婷婷 | 在线中文字幕网站 | 国产午夜av| 国产中文字幕视频在线观看 | 日韩视频免费播放 | 久久久免费精品国产一区二区 | 亚洲欧美国内爽妇网 | 久久久精品亚洲 | 在线天堂中文在线资源网 | 欧美日韩在线视频免费 | 国产1区在线| 在线视频1卡二卡三卡 | 能在线观看的日韩av | 天天操天天色天天射 | 少妇搡bbbb搡bbb搡69 | 日本夜夜草视频网站 | 久久1电影院 | 国产福利网站 | 五月婷网 | 一区二区中文字幕在线观看 | a成人v在线 | 综合网欧美 | 91视频免费观看 | 色婷婷激情网 | 亚州免费视频 | 国产在线一卡 | 色综合五月 | av天天澡天天爽天天av | 久久综合色天天久久综合图片 | 国产精品美女毛片真酒店 | av官网 | 久久久久国产成人精品亚洲午夜 | 久久久久久国产精品免费 | 成人资源在线播放 | 久久久影院一区二区三区 | 国产精品久久久久久爽爽爽 | 色婷婷色 | 在线免费三级 | 久久国产电影 | 一区中文字幕在线观看 | 97人人澡人人添人人爽超碰 | 久久免费视频99 | 91av在线视频免费观看 | 久草网站在线观看 | 中文字幕人成乱码在线观看 | 成人av久久 | 成人国产精品 | 精品美女久久久久 | 国产在线p | 99色婷婷 | 国产a网站| 在线观看不卡视频 | av高清在线 | 日韩在线观看你懂的 | 狠狠干2018| 国产精品成人一区二区 | 久久国色夜色精品国产 | 一二三精品视频 | 91激情| 成人免费网站视频 | 亚洲综合色网站 | 黄色大片中国 | 国产精品美女毛片真酒店 | 久久免费影院 | 日本三级中文字幕在线观看 | 国产日产精品久久久久快鸭 | 国产精品第一页在线观看 | www黄在线 | 中文字幕国产亚洲 | 日韩剧 | 欧美日韩一区二区三区在线免费观看 | 国产精品福利午夜在线观看 | 欧洲av在线 | 中文字幕在线观看免费高清完整版 | 超碰在线97免费 | 久久久久久视频 | 丁香五月缴情综合网 | 在线看毛片网站 | 亚洲黄色成人网 | 久久精品国产亚洲 | 91超碰免费在线 | 91网址在线观看 | 激情偷乱人伦小说视频在线观看 | 中文字幕av有码 | 天天躁日日躁狠狠躁av麻豆 | 中文永久字幕 | 中文字幕在线资源 | 亚洲精选视频在线 | 国内精品久久久久久久影视简单 | 奇米影视999| 日韩理论影院 | 四虎在线观看视频 | 欧美一区免费观看 | 日本视频高清 | 麻豆影视在线观看 | 亚洲精品国产精品国自产观看浪潮 | 国产黄色精品视频 | 国产精品亚州 | 91精品啪在线观看国产 | 深爱婷婷网 | 麻豆视频在线观看 | avsex| 日日夜操 | 色婷婷国产精品 | 天天av天天 | 18做爰免费视频网站 | 91精品区 | 视频一区二区免费 | 91网免费观看 | 午夜狠狠操 | 亚洲三级影院 | 久久亚洲综合国产精品99麻豆的功能介绍 | 日韩在线免费观看视频 | 久久久麻豆精品一区二区 | 亚洲免费视频观看 | 精品av网站 | 99c视频在线 | 精品视频免费久久久看 | 婷婷六月综合亚洲 | 国产探花视频在线播放 | 在线亚洲人成电影网站色www | 很黄很色很污的网站 | 精品国产一区二区在线 | 人人狠狠综合久久亚洲 | 中文字幕成人 | av网站免费线看精品 | 日韩中文久久 | 在线观看一区二区精品 | 五月天国产 | 亚洲黄色免费在线看 | 福利视频导航网址 | 一区二区三区精品在线视频 | 国产精品一区二区在线观看免费 | 中文字幕第一页在线播放 | 激情av网址 | 91九色蝌蚪国产 | 久久久久成人精品 | 免费观看一级成人毛片 | 亚洲影音先锋 | 亚洲专区免费观看 | 亚洲精品国偷拍自产在线观看蜜桃 | 视频在线亚洲 | 日韩欧美视频在线播放 | 国产精品视频内 | 99热最新网址 | 国产一区私人高清影院 | 最新色站 | 国产美女视频免费观看的网站 | 四虎国产精品永久在线国在线 | 久久国产亚洲精品 | 欧美一区二区三区激情视频 | 999国内精品永久免费视频 | 精品一区二区三区香蕉蜜桃 | 精品久久美女 | 久一网站 | 4438全国亚洲精品观看视频 | 天天碰天天操 | 免费精品在线视频 | 视频在线观看91 | 五月视频 | 超碰97免费观看 | 丁香婷婷激情国产高清秒播 | 国产亚洲一级高清 | 久久一区二区免费视频 | 国产精品国产三级国产aⅴ9色 | 99精品欧美一区二区 | 97国产大学生情侣酒店的特点 | 欧美日韩大片在线观看 | 久久精品视频免费观看 | 亚洲精品乱码久久久久久写真 | 日韩在线电影一区 | 97精品国产 | 亚洲精品自拍视频在线观看 | 99情趣网视频 | 婷婷丁香花 | 欧美一级片免费观看 | av在线8| 国产精品丝袜久久久久久久不卡 | 久草www | 午夜精品一二区 | 欧美色图视频一区 | 国产一级在线视频 | 国产成人精品国内自产拍免费看 | 九色自拍视频 | 婷婷亚洲综合五月天小说 | 久久精品亚洲 | 91丨九色丨首页 | 国产免费小视频 | 中文在线8资源库 | 精品国产成人av在线免 | 玖玖国产精品视频 | 欧美日韩国产亚洲乱码字幕 | 四虎影视成人永久免费观看视频 | 中文字幕精品www乱入免费视频 | 丁香婷婷激情国产高清秒播 | 操老逼免费视频 | 亚洲精品在线一区二区三区 | 久久久久久久av麻豆果冻 | 国产精品自在线 | 在线免费av电影 | 97品白浆高清久久久久久 | 国产黄大片在线观看 | 国产福利在线不卡 | 久久短视频 | 九九九九九九精品 | 国产精品国产亚洲精品看不卡15 | 国产精品99久久久精品免费观看 | 播五月婷婷 | 久草在线播放视频 | 中文字幕在线观看完整版电影 | 91亚洲在线| 久久er99热精品一区二区三区 | 日韩特级黄色片 | 国产不卡网站 | 欧美日韩国产一区二区在线观看 | av网址aaa| 久久久高清视频 | 激情久久伊人 | 五月天.com | 五月天婷亚洲天综合网鲁鲁鲁 | 免费黄色在线播放 | 日韩字幕在线观看 | 成人在线观看影院 | 国产视频中文字幕 | 91视频 - v11av| 国产91av视频在线观看 | 国产欧美日韩视频 | 成人国产精品入口 | 成人免费电影 | 天天综合天天做天天综合 | www.干| 国产精品一区二区你懂的 | 国产精品视频观看 | 香蕉视频在线看 | 中文字幕人成乱码在线观看 | 中文字幕人成一区 | 色欧美日韩 | 国产精品入口久久 | 久久香蕉电影网 | 久久亚洲区 | 五月婷婷开心 | 国产一二三精品 | 亚洲一区视频在线播放 | 国产黄在线免费观看 | 超碰在线观看99 | 国产二区精品 | 婷五月天激情 | 国产理论片在线观看 | 天天综合网在线 | 日韩在线观看网址 | www.色com| 免费看污黄网站 | 国产精品igao视频网网址 | 在线中文字幕观看 | 91视频久久久| 91麻豆看国产在线紧急地址 | 日韩欧美一区二区三区视频 | 911香蕉| 国产综合香蕉五月婷在线 | 欧美一二区视频 | 涩五月婷婷 | www.91成人 | 在线黄频 | 色视频网站在线观看一=区 a视频免费在线观看 | 国产精品麻豆三级一区视频 | 久草视频观看 | wwwwww国产| 日韩欧美一区二区三区在线 | 国产精品白虎 | 国产精品久久久久久一区二区三区 | 91九色蝌蚪视频在线 | 日韩精品1区2区 | 欧美日韩亚洲精品在线 | 久久在线看 | 日韩免费中文 | 国产精品一区二区果冻传媒 | 免费av网址在线观看 | 欧美一级片免费播放 | 激情小说网站亚洲综合网 | 国产91免费在线观看 | 日韩精品免费一区二区三区 | 免费a级大片 | 精品在线亚洲视频 | 国内精品美女在线观看 | 久久成人18免费网站 | 蜜臀av性久久久久蜜臀aⅴ涩爱 | 国产一级视频在线观看 | 在线中文字幕网站 | 国产成人精品国内自产拍免费看 | 正在播放日韩 | 婷婷丁香狠狠爱 | 中文字幕资源网在线观看 | 人人干人人搞 | 在线免费高清一区二区三区 | 免费观看成年人视频 | 激情久久婷婷 | 国产精品久久久久婷婷 | 91视频免费看片 | 国产又粗又硬又长又爽的视频 | 激情网站免费观看 | 久久精品电影院 | 欧美少妇的秘密 | 中文字幕免费中文 | 免费在线观看成年人视频 | 精品一区电影国产 | 欧美最猛性xxxxx(亚洲精品) | 欧美一区二区视频97 | 天天操导航| 五月丁婷婷 | 波多野结衣一区 | 久久久福利视频 | 免费看黄网站在线 | 日本在线视频网址 | 免费在线观看a v | 免费亚洲成人 | 国产成人免费观看久久久 | 久久人操| 国产亚洲精品美女久久 | 91完整视频 | 天天色成人网 | 国产精品va在线观看入 | 久久精品首页 | 97**国产露脸精品国产 | 99久高清在线观看视频99精品热在线观看视频 | 免费av看片 | 国产一级高清视频 | 韩国av一区二区三区 | 国产高清在线a视频大全 | 国产成人精品久久亚洲高清不卡 | 欧美国产日韩久久 | 色综合天天色综合 | 91麻豆精品国产91久久久更新时间 | 成人av电影在线观看 | 国产成人a亚洲精品 | 在线观看的av | 国产日韩欧美精品在线观看 | 亚洲综合在线一区二区三区 | 久久99国产视频 | 香蕉看片| 亚洲成人精品 | 日韩视频区 | 亚洲日本中文字幕在线观看 | 毛片基地黄久久久久久天堂 | 亚洲欧美在线观看视频 | 国产精品第2页 | 97精品国产91久久久久久久 | 一区二区三区电影大全 | 国产在线v | 狂野欧美激情性xxxx | 久久精品久久精品久久 | 中文字幕av最新 | 91完整版 | 69国产精品视频 | 丁香六月色 | 亚洲久草视频 | 久久精品一二三区白丝高潮 | 国产aaa毛片 | 丁香在线观看完整电影视频 | 91麻豆精品91久久久久同性 | 欧美一区二区三区在线 | 欧美精品一区二区在线播放 | 开心激情五月婷婷 | 国产成人精品综合久久久久99 | 日本精品视频在线播放 | 免费网站v| 综合网av| 人人澡超碰碰 | 波多野结衣在线播放视频 | 99热这里| 色资源网免费观看视频 | 亚洲高清资源 | 日韩精品久久久久久久电影99爱 | 国产精品欧美一区二区三区不卡 | 五月天com| 日韩久久精品一区二区 | 最新国产精品久久精品 | 日韩av中文 | 涩涩伊人| 亚洲一区二区观看 | 亚洲天堂网视频 | 中文电影网 | 在线观看国产区 | 91精品国自产在线偷拍蜜桃 | 亚洲欧洲xxxx | 日韩一级片观看 | 天堂av网在线 | 四虎影视精品 | 久久久九色精品国产一区二区三区 | 超碰免费成人 | 在线观看免费av片 | 国产中文字幕网 | 国产精品igao视频网网址 | 男女激情免费网站 | 91精品一区国产高清在线gif | 国产专区在线看 | 欧美日韩国产成人 | 在线精品观看国产 | 久草在线观看资源 | 国产一级视频 | 麻豆高清免费国产一区 | 精品主播网红福利资源观看 | 色综合久久久久综合体 | 国产精品一区在线 | 国产99久久九九精品 | 天天躁天天狠天天透 | 五月婷婷操 | 伊人国产在线观看 | 成人免费xxx在线观看 | 免费在线h| 免费色视频 | 精品在线播放视频 | 国产亚洲综合性久久久影院 | 超碰在线9 | 色wwwww | 成人av动漫在线 | 日韩精品最新在线观看 | 人人舔人人舔 | 在线观看黄色免费视频 | 免费视频网| 成人av影院在线观看 | 九九九免费视频 | 免费视频资源 | 亚洲影视资源 | 中文字幕乱偷在线 | 亚洲综合色av | av中文字幕在线观看网站 | 久久艹在线 | 久久综合免费视频影院 | 天天做天天爱天天爽综合网 | 久久久久影视 | 国产粉嫩在线观看 | 天天人人综合 | 91视频高清免费 | 91视频啪| 玖玖视频国产 | 黄污视频大全 | 在线观看岛国 | 伊人久久婷婷 | 91成人欧美 | 国内成人精品视频 | 日日夜夜操操操操 | 高清有码中文字幕 | 女人高潮特级毛片 | 欧美va电影| 国产97在线播放 | 日韩午夜av电影 | 一区二区三区免费在线观看视频 | 超碰在线人人 | 日韩欧美一级二级 | 久久久久精| 91视频网址入口 | 啪啪免费观看网站 | 五月天久久婷婷 | 久久官网 | 人人看97 | 久久中文字幕视频 | 日韩理论在线播放 | 日韩欧美在线国产 | 久久夜色网 | 蜜臀久久99精品久久久酒店新书 | 99免费在线视频观看 | 欧美日韩网址 | 国产精品av免费在线观看 | 人人草人 | 日韩精品 在线视频 | 精品国产成人av在线免 | 97超碰超碰久久福利超碰 | 操操综合 | 亚洲综合视频在线 | 欧美在一区 | 免费在线观看成人av | 国色天香第二季 | 色综合久久天天 | 日韩免费三级 | 天天操夜夜爱 | 黄色动态图xx | 日本午夜在线亚洲.国产 | 久久精品女人毛片国产 | 久久色中文字幕 | 激情欧美日韩一区二区 | 日韩精品久久久久久 | 日韩在线观看a | 日韩久久精品一区二区 | 激情婷婷在线 | 超碰在线观看av.com | 中文字幕日韩免费视频 | 九九久久久 | 欧美日韩高清在线一区 | 久久xx视频 | 亚洲 欧洲av | 精品久久久久久国产91 | 久久国产精品免费观看 | 偷拍精品一区二区三区 | 久久精品国产免费 | 国产一区二区在线观看免费 | 免费污片 | 97超碰总站 | 国产h在线播放 | 久久黄色免费视频 | 黄色av大片 | 国产亚洲高清视频 | 精品在线免费观看 | 欧美在线久久 | 在线看日韩av | 成人在线观看免费视频 | 色www.| 国产在线观看91 | 成人av在线资源 | 日韩久久网站 | 最新一区二区三区 | 久久免费播放视频 | 亚洲一区二区视频在线播放 | 又大又硬又黄又爽视频在线观看 | 人人插人人澡 | 日韩精品一区二区三区第95 | 九九免费观看视频 | 国产日韩精品一区二区三区在线 | 精品国产乱码一区二区三区在线 | 国产精品a久久久久 | 一区二区不卡视频在线观看 | 日韩精品无码一区二区三区 | 国产美女视频黄a视频免费 久久综合九色欧美综合狠狠 | 超碰人人乐 | 高清av在线 | 久久综合99| 五月天婷婷视频 | 99精品在线视频播放 | 中文字幕综合在线 | 国产成年免费视频 | 国产成人一区二区三区在线观看 | 99久久精品国产一区二区三区 | 中文字幕中文字幕 | www.黄色片网站 | 久久精品视频在线看 | 正在播放亚洲精品 | 久久久国产高清 | 91桃色国产在线播放 | 伊人狠狠干 | 91九色蝌蚪国产 | 五月婷婷激情 | 亚洲综合色视频在线观看 | 欧美最猛性xxxxx亚洲精品 | 一区二区亚洲精品 | 成年人看片 | 国产一区免费视频 | 日韩av成人免费看 | 国产最新视频在线 | 香蕉视频在线视频 | 国产精品久久久久久久久久直播 | 天天干视频在线 | 国产成人一区三区 | 国产精品成人自产拍在线观看 | 97成人资源 | 国产精品久久视频 | 99r在线播放 | 亚洲视频久久久久 | 97在线精品国自产拍中文 | 天天干天天综合 | 欧美肥妇free | 丁香资源影视免费观看 | 2020天天干天天操 | 亚洲精品无 | 婷婷丁香激情综合 | 婷婷色中文 | 色综合久久88色综合天天 | 97品白浆高清久久久久久 | 国产高清av | 激情婷婷综合 | 免费视频在线观看网站 | 日韩精品最新在线观看 | 亚洲精品网页 | 午夜精品久久久久久久久久久 | 五月天亚洲激情 | 国产成人综 | 久久在线视频在线 | 亚洲天堂网在线视频观看 | 婷婷五情天综123 | 深爱婷婷久久综合 | 久久久久久免费视频 | 欧美国产日韩久久 | 成人在线小视频 | 成人av免费在线观看 | 久久综合久久综合这里只有精品 | 国产一级做a | 久久精品久久久精品美女 | 国产精品乱码在线 | 91精品视频一区 | 国产字幕在线观看 | 久久精品一区二区 | 欧美一级久久 | 五月天婷婷在线观看视频 | 日日操夜夜操狠狠操 | 久久久国产一区 | 久久免费精品一区二区三区 | 国产区欧美| 久久久久高清毛片一级 | 一区在线观看 | 18国产精品白浆在线观看免费 | 亚洲日本韩国一区二区 | 色干干 | 亚洲欧美激情精品一区二区 | 久久久 精品 | av电影av在线| 成人免费毛片aaaaaa片 | 亚洲欧美日韩一级 | 四季av综合网站 | 欧美伦理一区 | 亚洲精品啊啊啊 | 国产在线综合视频 | 国产精品成人在线观看 | 久久精品最新 | 91免费看片黄 | 伊人午夜| 色天天久久 | 波多野结衣精品在线 | 夜夜躁狠狠躁日日躁视频黑人 | 欧美日韩免费网站 | 美女视频永久黄网站免费观看国产 | 免费久久99精品国产 | 国产精品一区一区三区 | 日本色小说视频 | 欧美孕妇视频 | 久久在线看 | 五月综合色婷婷 | 免费看网站在线 | 日日干日日操 | 亚洲精品美女久久久久网站 | 爱射综合| 91日韩国产| 天天操天天谢 | 亚洲一二视频 | 亚洲精品小视频 | 国产美女免费视频 | wwwwww色 | 久久久999精品视频 国产美女免费观看 | 久久精品视频国产 | 91热爆在线观看 | 国色天香第二季 | 国产涩图| 欧美午夜激情网 | 三日本三级少妇三级99 | 免费在线电影网址大全 | 久久av影院 | 狠狠狠狠干 | 日韩在线观看网站 | 91亚洲精品久久久蜜桃网站 | 久久免费av电影 | 黄色av电影在线观看 | 狠狠色丁香久久婷婷综合五月 | 国产乱老熟视频网88av | www.天天射.com | 精品免费一区二区三区 | 国产成人一区二区精品非洲 | 99精品国产高清在线观看 | 国产黄a三级 | 国产成人精品aaa | 在线观看中文字幕av | 黄色大全免费网站 | 久久久久久免费毛片精品 | 日韩av高清在线观看 | 91麻豆传媒 | 亚洲狠狠| 97在线免费观看 | 欧美三级高清 | 日韩亚洲在线 | 国色天香永久免费 | 国产免费叼嘿网站免费 | 99热99| 成年人视频免费在线播放 | 在线免费视频你懂的 | 免费看黄在线网站 | 国产精品毛片一区二区 | 日韩激情久久 | av一区二区在线观看中文字幕 | 丰满少妇在线观看 | 成人一级在线观看 | 17videosex性欧美| 色网站黄| 天天干天天干天天操 | 亚洲精品乱码久久久久v最新版 | av网站在线观看免费 | 人人爱爱 | 黄色美女免费网站 | 久久久久久蜜桃一区二区 | 久久久免费少妇 | 一级片免费在线 | 国产在线欧美日韩 | 91精品国产99久久久久 | 成人av免费电影 | av色网站| 日日日操 | 久久精品—区二区三区 | 久久久久久久网 | 五月婷婷丁香在线观看 | 久久夜夜夜| 综合国产在线观看 | 国产精品一区二区精品视频免费看 | 西西人体www444 | 婷婷国产精品 | 日韩视频图片 | 国产视频亚洲视频 | 国产精品久久久久婷婷二区次 | 日韩国产精品久久久久久亚洲 | 精品a在线 | 国产乱对白刺激视频在线观看女王 | 人九九精品 | 丁香激情综合久久伊人久久 | 九七在线视频 | 91精品伦理 | 亚洲老妇xxxxxx| 日韩精品一区二区在线 | 五月婷婷综合在线 | 欧美一级片在线播放 | 欧美激情精品久久久 | 国产一级二级在线观看 | 亚洲无毛专区 | 国产成人高清 | 国产视频资源 | 午夜久草 | 一个色综合网站 | 国产精品久久一区二区三区不卡 | 免费在线观看av网站 | 久久九九国产视频 | 日韩免费观看av | 久久久高清免费视频 | 五月视频| 中文字幕在线观看你懂的 | 精品国产视频一区 | 91av官网 | 日韩av影视在线 | 中字幕视频在线永久在线观看免费 | 91精品国产成人www | 国产电影黄色av | 国产69精品久久久久久 | 久久五月婷婷丁香 | 日韩三级不卡 | 国产一二三区av | 91视频在线自拍 | 久久综合狠狠狠色97 | 视频在线在亚洲 | 日韩精品一区二区在线观看视频 | 久久免费视频5 | 亚洲aⅴ在线观看 | 色视频 在线| 9999在线| 免费看黄色小说的网站 | 插插插色综合 | 婷婷新五月 | 久久中文字幕在线视频 | 欧美福利网站 | 天天操操| 人人插人人| 久久涩涩网站 | 精品国产三级a∨在线欧美 免费一级片在线观看 | 国产中文字幕91 | 一本一本久久a久久精品综合小说 | 日韩理论| 久久久久国产精品一区 | 天天操天天爽天天干 | 97人人精品 | 精品国产成人在线影院 | 色婷婷视频 | 国产色啪| 91久久人澡人人添人人爽欧美 | 国产福利在线免费 | 国产中文视频 | 天天干,狠狠干 | 国产乱老熟视频网88av | av黄免费看 | 就操操久久 | 人人cao| 中文av字幕在线观看 | 日韩在线观看你懂得 | 国产精品99蜜臀久久不卡二区 | 久久y | 免费视频一级片 | 亚洲精品国精品久久99热一 | 91精品麻豆 | 波多野结衣视频一区二区三区 | 色香蕉网 | 9999激情 | 日韩女同av | 国产不卡一二三区 | 毛片视频网址 | 国产视频在线观看一区 | 91人人澡 | 狠狠狠狠狠狠天天爱 | 九九热精品在线 | 亚洲日本在线视频观看 | 91九色视频网站 | 日韩电影在线视频 | 欧美日韩国产在线观看 | 91成人免费看 | 欧美性大战久久久久 | 国内久久精品 | av再线观看| 日韩超碰在线 | 国产老太婆免费交性大片 | 国产精品九九九九九九 | 久久久久久久网 | 欧美贵妇性狂欢 | 国产精品久久久久久久久久尿 | 国产99久久精品一区二区300 | 国产麻豆果冻传媒在线观看 | 亚洲精品国偷拍自产在线观看蜜桃 | 国产精品久久久久av免费 | 亚洲国产日韩一区 | 亚洲一级二级三级 | 97视频免费观看 | 国产精品视频免费在线观看 | 91福利小视频 | 欧美日韩国产一区二区在线观看 | 四虎在线视频免费观看 | 久久精品一区二区三区中文字幕 | 欧美一进一出抽搐大尺度视频 | 麻豆免费视频观看 | 午夜精品久久久久久久99水蜜桃 | 中文字幕免费高清 | 久艹视频在线观看 | 日韩在线观看视频一区二区三区 | 97人人添人澡人人爽超碰动图 | 国产高清黄色 | 色综合天天综合网国产成人网 | 国产精品入口麻豆www | 成人免费视频在线观看 | 亚洲高清免费在线 | 国产小视频你懂的在线 | 九九九九热精品免费视频点播观看 | 国产一级二级三级在线观看 | 91在线观看黄| 日本久久久久久久久久久 | 91av视频在线播放 | 国产美女视频免费 | 在线色吧 | 亚洲天堂在线观看完整版 | 久久精品国产一区二区 | 日韩羞羞| 婷婷伊人网 | 免费黄色网止 | 9久久精品 | 国产一卡二卡四卡国 | 国产精品久久久久久久久蜜臀 | 日日草天天干 | 国产精品国产三级国产aⅴ入口 | 一区二区电影在线观看 | 天天色天天色 | 久久66热这里只有精品 | 人人干网站 | 免费a视频在线观看 | 日韩高清免费无专码区 | 亚洲中字幕| 国产高清视频在线免费观看 | 天天操天天摸天天爽 | 日韩精品久久久久久久电影99爱 | 在线观看日韩国产 | 91网免费观看 | 亚洲精品国产第一综合99久久 | 亚洲四虎在线 | 黄色a在线观看 | av手机版 | 色香蕉网 | av在线官网 | 免费在线观看一级片 | 97在线视频免费观看 | 久久www免费人成看片高清 | 丁香婷婷久久 | 一区在线观看视频 | 99免费在线观看视频 | 欧美激情视频一二区 | 麻豆久久精品 | 亚洲更新最快 | 国产99久久久欧美黑人 | 久久亚洲私人国产精品 | 精品国产成人av在线免 | 精品播放 | 欧美精品一区二区三区一线天视频 | 国产精品日韩在线观看 | 婷婷激情综合五月天 | 97视频在线免费播放 | 成人97人人超碰人人99 | 波多野结衣视频在线 | 欧美夫妻生活视频 | 免费网站黄 | 一区二区三区四区在线免费观看 | 国产精品九九久久久久久久 | 精品国产激情 | 久久人人爽人人爽人人片 | 国产综合香蕉五月婷在线 | 91理论片午午伦夜理片久久 | 婷婷色中文网 | 久久理论片 | 国产又粗又猛又色又黄网站 | 精品一区二区在线免费观看 | 日韩,精品电影 | 天天操狠狠操网站 | 在线播放 一区 | 日本精品久久久久 | 三上悠亚一区二区在线观看 | 天天草天天草 | 亚洲天天干 | 国产糖心vlog在线观看 | www.色五月| 久久久久久伊人 | 在线岛国av | 精品不卡av | 九草视频在线 | 久久天天躁狠狠躁亚洲综合公司 | 制服丝袜一区二区 | 国产亚洲综合性久久久影院 | 国产精品视频地址 | 99久久久国产精品免费99 | 超碰在线官网 | а天堂中文最新一区二区三区 | 激情电影在线观看 | 天堂激情网 | 日日操网站 | 国产亚洲人| bbbb操bbbb | 深夜激情影院 | 爱射综合 | 91麻豆精品国产自产 | 国产高清视频在线观看 | 天天透天天插 | 欧美日韩亚洲在线观看 | 在线观看国产一区 | 日韩高清久久 | 亚洲成人网av | 久久久久久久久久久影视 | 国产精品免费观看视频 | 99精品免费久久久久久久久 | 日日夜夜天天射 | 91精品黄色 | 五月天综合激情 | 国产免费资源 | 久久理论视频 | 97精品国产| 久久久三级视频 | 亚洲精品2区 | 91久久精品日日躁夜夜躁国产 | 亚洲视频aaa | 欧美日韩国产在线精品 | 91看片看淫黄大片 | 日韩免费网址 | 97超碰在线久草超碰在线观看 | 日本一区二区免费在线观看 | 久草免费在线视频观看 | 色综合久久88 | 久久在线免费观看视频 | 免费在线观看成人av | 激情婷婷在线观看 | 国产中文在线视频 | 午夜美女影院 | 国产精品精品国产婷婷这里av | 日韩精品一区二区三区在线播放 | 国产黄色一级片 | 免费亚洲精品视频 | 91传媒在线播放 | 中文字幕最新精品 | 人人舔人人爱 | 久久精品久久99精品久久 | 九九有精品 | 国产一区二区在线观看视频 | 全黄网站| 国产福利一区二区三区在线观看 | 亚洲精品五月天 | 亚洲高清在线 | 2019中文字幕网站 | 夜夜躁日日躁狠狠久久88av | 欧美久久影院 | 亚洲va欧美 | 二区三区在线视频 | 国产精品亚洲a | 在线免费观看的av | 日本免费久久高清视频 | 亚洲国产99| 久久国产片 | 亚洲涩涩涩 | 久久精品久久久精品美女 | 久久婷综合 | 久久精品国产亚洲精品 |