成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Linux系統(tǒng)休眠(System Suspend)和設(shè)備中斷處理

系統(tǒng) Linux 開發(fā)工具
主要解決這樣一個問題:在系統(tǒng)休眠過程中,如何suspend設(shè)備中斷(IRQ)?在從休眠中喚醒的過程中,如何resume設(shè)備IRQ?

一、設(shè)備IRQ的suspend和resume

主要解決這樣一個問題:在系統(tǒng)休眠過程中,如何suspend設(shè)備中斷(IRQ)?在從休眠中喚醒的過程中,如何resume設(shè)備IRQ?

一般而言,在系統(tǒng)suspend過程的后期,各個設(shè)備的IRQ (interrupt request line)會被disable掉。具體的時間點是在各個設(shè)備的late suspend階段之后。代碼如下(刪除了部分無關(guān)代碼):

  1. static int suspend_enter(suspend_state_t state, bool *wakeup) 
  2.  
  3. {…… 
  4.  
  5. error = dpm_suspend_late(PMSG_SUSPEND);-----late suspend階段 
  6.  
  7. error = platform_suspend_prepare_late(state); 
  8.  
  9. 下面的代碼中會disable各個設(shè)備的irq 
  10.  
  11. error = dpm_suspend_noirq(PMSG_SUSPEND);----進入noirq的階段 
  12.  
  13. error = platform_suspend_prepare_noirq(state); 
  14.  
  15. …… 
  16.  
  17.  

在dpm_suspend_noirq函數(shù)中,會針對系統(tǒng)中的每一個device,依次調(diào)用device_suspend_noirq來執(zhí)行該設(shè)備noirq情況下的suspend callback函數(shù),當(dāng)然,在此之前會調(diào)用suspend_device_irqs函數(shù)來disable所有設(shè)備的irq。

之所以這么做,其思路是這樣的:在各個設(shè)備驅(qū)動完成了late suspend之后,按理說這些已經(jīng)被suspend的設(shè)備不應(yīng)該再觸發(fā)中斷了。如果還有一些設(shè)備沒有被正確的suspend,那么我們最好的策略是mask該設(shè)備的irq,從而阻止中斷的遞交。此外,在過去的代碼中(指interrupt handler),我們對設(shè)備共享IRQ的情況處理的不是很好,存在這樣的問題:在共享IRQ的設(shè)備們完成suspend之后,如果有中斷觸發(fā),這時候設(shè)備驅(qū)動的interrupt handler并沒有準備好。在有些場景下,interrupt handler會訪問已經(jīng)suspend設(shè)備的IO地址空間,從而導(dǎo)致不可預(yù)知的issue。這些issue很難debug,因此,我們引入了suspend_device_irqs()以及設(shè)備noirq階段的callback函數(shù)。

系統(tǒng)resume過程中,在各個設(shè)備的early resume過程之前,各個設(shè)備的IRQ會被重新打開,具體代碼如下(刪除了部分無關(guān)代碼):

  1. static int suspend_enter(suspend_state_t state, bool *wakeup) 
  2.  
  3. {…… 
  4.  
  5. platform_resume_noirq(state);----首先執(zhí)行noirq階段的resume 
  6.  
  7. dpm_resume_noirq(PMSG_RESUME);------在這里會恢復(fù)irq,然后進入early resume階段 
  8.  
  9. platform_resume_early(state); 
  10.  
  11. dpm_resume_early(PMSG_RESUME); 
  12.  
  13. ……}  

在dpm_resume_noirq函數(shù)中,會調(diào)用各個設(shè)備驅(qū)動的noirq callback,在此之后,調(diào)用resume_device_irqs函數(shù),完成各個設(shè)備irq的enable。

二、關(guān)于IRQF_NO_SUSPEND Flag

當(dāng)然,有些中斷需要在整個系統(tǒng)的suspend-resume過程中(包括在noirq階段,包括將nonboot CPU推送到offline狀態(tài)以及系統(tǒng)resume后,將其重新設(shè)置為online的階段)保持能夠觸發(fā)的狀態(tài)。一個簡單的例子就是timer中斷,此外IPI以及一些特殊目的設(shè)備中斷也需要如此。

在中斷申請的時候,IRQF_NO_SUSPEND flag可以用來告知IRQ subsystem,這個中斷就是上一段文字中描述的那種中斷:需要在系統(tǒng)的suspend-resume過程中保持enable狀態(tài)。有了這個flag,suspend_device_irqs并不會disable該IRQ,從而讓該中斷在隨后的suspend和resume過程中,保持中斷開啟。當(dāng)然,這并不能保證該中斷可以將系統(tǒng)喚醒。如果想要達到喚醒的目的,請調(diào)用enable_irq_wake。

需要注意的是:IRQF_NO_SUSPEND flag影響使用該IRQ的所有外設(shè)(一個IRQ可以被多個外設(shè)共享,不過ARM中不會這么用)。如果一個IRQ被多個外設(shè)共享,并且各個外設(shè)都注冊了對應(yīng)的interrupt handler,如果其一在申請中斷的時候使用了IRQF_NO_SUSPEND flag,那么在系統(tǒng)suspend的時候(指suspend_device_irqs之后,按理說各個IRQ已經(jīng)被disable了),所有該IRQ上的各個設(shè)備的interrupt handler都可以被正常的被觸發(fā)執(zhí)行,即便是有些設(shè)備在調(diào)用request_irq(或者其他中斷注冊函數(shù))的時候沒有設(shè)定IRQF_NO_SUSPEND flag。正因為如此,我們應(yīng)該盡可能的避免同時使用IRQF_NO_SUSPEND 和IRQF_SHARED這兩個flag。

三、系統(tǒng)中斷喚醒接口:enable_irq_wake() 和 disable_irq_wake()

有些中斷可以將系統(tǒng)從睡眠狀態(tài)中喚醒,我們稱之“可以喚醒系統(tǒng)的中斷”,當(dāng)然,“可以喚醒系統(tǒng)的中斷”需要配置才能啟動喚醒系統(tǒng)這樣的功能。這樣的中斷一般在工作狀態(tài)的時候就是作為普通I/O interrupt出現(xiàn),只要在準備使能喚醒系統(tǒng)功能的時候,才會發(fā)起一些特別的配置和設(shè)定。

這樣的配置和設(shè)定有可能是和硬件系統(tǒng)(例如SOC)上的信號處理邏輯相關(guān)的,我們可以考慮下面的HW block圖:

 

外設(shè)的中斷信號被送到“通用的中斷信號處理模塊”和“特定中斷信號接收模塊”。正常工作的時候,我們會turn on“通用的中斷信號處理模塊”的處理邏輯,而turn off“特定中斷信號接收模塊” 的處理邏輯。但是,在系統(tǒng)進入睡眠狀態(tài)的時候,有可能“通用的中斷信號處理模塊”已經(jīng)off了,這時候,我們需要啟動“特定中斷信號接收模塊”來接收中斷信號,從而讓系統(tǒng)suspend-resume模塊(它往往是suspend狀態(tài)時候唯一能夠工作的HW block了)可以正常的被該中斷信號喚醒。一旦喚醒,我們最好是turn off“特定中斷信號接收模塊”,讓外設(shè)的中斷處理回到正常的工作模式,同時,也避免了系統(tǒng)suspend-resume模塊收到不必要的干擾。

IRQ子系統(tǒng)提供了兩個接口函數(shù)來完成這個功能:enable_irq_wake()函數(shù)用來打開該外設(shè)中斷線通往系統(tǒng)電源管理模塊(也就是上面的suspend-resume模塊)之路,另外一個接口是disable_irq_wake(),用來關(guān)閉該外設(shè)中斷線通往系統(tǒng)電源管理模塊路徑上的各種HW block。

調(diào)用了enable_irq_wake會影響系統(tǒng)suspend過程中的suspend_device_irqs處理,代碼如下:

  1. static bool suspend_device_irq(struct irq_desc *desc
  2.  
  3.  
  4. …… 
  5.  
  6. if (irqd_is_wakeup_set(&desc->irq_data)) { 
  7.  
  8. irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED); 
  9.  
  10. return true
  11.  
  12.  
  13. 省略Disable 中斷的代碼 
  14.  
  15.  

也就是說,一旦調(diào)用enable_irq_wake設(shè)定了該設(shè)備的中斷作為系統(tǒng)suspend的喚醒源,那么在該外設(shè)的中斷不會被disable,只是被標記一個IRQD_WAKEUP_ARMED的標記。對于那些不是wakeup source的中斷,在suspend_device_irq 函數(shù)中會標記IRQS_SUSPENDED并disable該設(shè)備的irq。在系統(tǒng)喚醒過程中(resume_device_irqs),被diable的中斷會重新enable。

當(dāng)然,如果在suspend的過程中發(fā)生了某些事件(例如wakeup source產(chǎn)生了有效信號),從而導(dǎo)致本次suspend abort,那么這個abort事件也會通知到PM core模塊。事件并不需要被立刻通知到PM core模塊,一般而言,suspend thread會在某些點上去檢查pending的wakeup event。

在系統(tǒng)suspend的過程中,每一個來自wakeup source的中斷都會終止suspend過程或者將系統(tǒng)喚醒(如果系統(tǒng)已經(jīng)進入suspend狀態(tài))。但是,在執(zhí)行了suspend_device_irqs之后,普通的中斷被屏蔽了,這時候,即便HW觸發(fā)了中斷信號也無法執(zhí)行其interrupt handler。作為wakeup source的IRQ會怎樣呢?雖然它的中斷沒有被mask掉,但是其interrupt handler也不會執(zhí)行(這時候的HW Signal只是用來喚醒系統(tǒng))。唯一有機會執(zhí)行的interrupt handler是那些標記IRQF_NO_SUSPEND flag的IRQ,因為它們的中斷始終是enable的。當(dāng)然,這些中斷不應(yīng)該調(diào)用enable_irq_wake進行喚醒源的設(shè)定。

四、Interrupts and Suspend-to-Idle

Suspend-to-idle (也被稱為"freeze" 狀態(tài))是一個相對比較新的系統(tǒng)電源管理狀態(tài),相關(guān)代碼如下:

  1. static int suspend_enter(suspend_state_t state, bool *wakeup) 
  2.  
  3.  
  4. …… 
  5.  
  6. 各個設(shè)備的late suspend階段 
  7.  
  8. 各個設(shè)備的noirq suspend階段 
  9.  
  10. if (state == PM_SUSPEND_FREEZE) { 
  11.  
  12. freeze_enter(); 
  13.  
  14. goto Platform_wake; 
  15.  
  16.  
  17. …… 
  18.  
  19.  

Freeze和suspend的前面的操作基本是一樣的:首先凍結(jié)系統(tǒng)中的進程,然后是suspend系統(tǒng)中的形形色色的device,不一樣的地方在noirq suspend完成之后,freeze不會disable那些non-BSP的處理器和syscore suspend階段,而是調(diào)用freeze_enter函數(shù),把所有的處理器推送到idle狀態(tài)。這時候,任何的enable的中斷都可以將系統(tǒng)喚醒。而這也就意味著那些標記IRQF_NO_SUSPEND(其IRQ沒有在suspend_device_irqs過程中被mask掉)是有能力將處理器從idle狀態(tài)中喚醒(不過,需要注意的是:這種信號并不會觸發(fā)一個系統(tǒng)喚醒信號),而普通中斷由于其IRQ被disable了,因此無法喚醒idle狀態(tài)中的處理器。

那些能夠喚醒系統(tǒng)的wakeup interrupt呢?由于其中斷沒有被mask掉,因此也可以將系統(tǒng)從suspend-to-idle狀態(tài)中喚醒。整個過程和將系統(tǒng)從suspend狀態(tài)中喚醒一樣,唯一不同的是:將系統(tǒng)從freeze狀態(tài)喚醒走的中斷處理路徑,而將系統(tǒng)從suspend狀態(tài)喚醒走的喚醒處理路徑,需要電源管理HW BLOCK中特別的中斷處理邏輯的參與。

五、IRQF_NO_SUSPEND 標志和enable_irq_wake函數(shù)不能同時使用

針對一個設(shè)備,在申請中斷的時候使用IRQF_NO_SUSPEND flag,又同時調(diào)用enable_irq_wake設(shè)定喚醒源是不合理的,主要原因如下:

1、如果IRQ沒有共享,使用IRQF_NO_SUSPEND flag說明你想要在整個系統(tǒng)的suspend-resume過程中(包括suspend_device_irqs之后的階段)保持中斷打開以便正常的調(diào)用其interrupt handler。而調(diào)用enable_irq_wake函數(shù)則說明你想要將該設(shè)備的irq信號設(shè)定為中斷源,因此并不期望調(diào)用其interrupt handler。而這兩個需求明顯是互斥的。

2、IRQF_NO_SUSPEND 標志和enable_irq_wake函數(shù)都不是針對一個interrupt handler的,而是針對該IRQ上的所有注冊的handler的。在一個IRQ上共享喚醒源以及no suspend中斷源是比較荒謬的。

不過,在非常特殊的場合下,一個IRQ可以被設(shè)定為wakeup source,同時也設(shè)定IRQF_NO_SUSPEND 標志。為了代碼邏輯正確,該設(shè)備的驅(qū)動代碼需要滿足一些特別的需求。

參考文獻

1、內(nèi)核文檔power/suspend-and-interrupts.txt 

責(zé)任編輯:龐桂玉 來源: 嵌入式Linux中文站
相關(guān)推薦

2021-12-28 08:38:26

Linux 中斷喚醒系統(tǒng)Linux 系統(tǒng)

2021-12-14 08:51:23

Linux 中斷子系統(tǒng)Linux 系統(tǒng)

2023-09-27 15:41:32

Linux系統(tǒng)

2020-12-29 09:11:33

LinuxLinux內(nèi)核

2013-10-11 13:01:45

LinuxLinux Shell

2021-12-10 08:45:45

Linux GIC Linux 系統(tǒng)

2021-12-08 08:41:31

Linux 中斷子系統(tǒng)Linux 系統(tǒng)

2021-11-02 10:53:56

Linux機制CPU

2021-08-10 11:30:30

Linux代碼中斷控制器

2021-08-03 15:10:26

Linux代碼驅(qū)動

2009-09-01 09:14:42

2012-06-01 15:39:46

休眠狀態(tài)墓碑狀態(tài)

2010-06-18 12:38:31

Linux acpi

2009-10-22 12:27:30

linux塊設(shè)備

2013-12-09 11:28:44

2020-12-03 08:59:06

Linux設(shè)備驅(qū)動

2017-07-14 14:35:27

Linux中斷系統(tǒng)

2013-10-16 13:53:54

Power SysteLinux開源系統(tǒng)

2010-03-03 14:30:35

Linux睡眠休眠

2020-05-08 16:39:01

內(nèi)存系統(tǒng)架構(gòu)Linux
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 免费在线成人 | 国产成人精品av | 久久精品视频在线观看 | www.日日干 | 午夜精品视频 | 精品视频一区二区 | 性高朝久久久久久久3小时 av一区二区三区四区 | 超碰97人人人人人蜜桃 | 亚洲成人在线免费 | 免费视频一区二区 | 久久精品久久久久久 | 蜜桃精品视频在线 | 国产在线不卡 | 成人性生交大片免费看r链接 | 夜夜草| 久久精品国产一区二区电影 | 一区二区三区视频在线观看 | 亚洲综合激情 | 亚洲精品久久国产高清情趣图文 | 国产精品1区2区3区 中文字幕一区二区三区四区 | 日韩一二三区视频 | 午夜视频网 | 日韩三区在线 | 国产女人与拘做受视频 | 欧美黄在线观看 | 欧美国产日韩在线 | 在线亚洲人成电影网站色www | 97超碰在线免费 | 国产综合精品一区二区三区 | 99热在线播放 | 精品一二区 | 国产欧美日韩在线播放 | 日韩一区在线观看视频 | 精品一区二区三区在线观看国产 | 成人在线免费视频 | 免费一级毛片 | 久久在线| 四虎永久 | 国产一区免费视频 | 久久99蜜桃综合影院免费观看 | 日本在线看片 |