国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

msm8916平臺Linux watchdog詳解(2)

2019-11-09 18:29:55
字體:
來源:轉載
供稿:網友

介紹高通msm8916中CONFIG_MSM_WATCHDOG_V2宏打開之后,watchdog是怎么工作的。 這個watchdog跟硬件相關,主要檢查當前是否有頻繁的中斷發生導致整個內核調度都出現問題。[LOCKUP_DETECTOR與MSM_WATCHDOG_V2的區別?]

這個宏很簡單,所涉及的文件就只有一個drivers/soc/qcom/watchdog_v2.c文件。 相關的device tree定義如下

qcom,wdt@b017000 { compatible = "qcom,msm-watchdog"; reg = <0xb017000 0x1000>; reg-names = "wdt-base"; interrupts = <0 3 0>, <0 4 0>; qcom,bark-time = <20000>; //bark時間20秒,20秒之內沒有喂狗,會觸發中斷 qcom,pet-time = <10000>;//pet時間10秒,表示每10秒喂一次狗 qcom,ipi-ping; };

這個device tree內容在下面函數里邊解析,下面內容可以看一下驅動里邊是怎么操作resource地址空間的!!!

(1) devm_request_mem_region()[iomem_resource](2) pdata->base = devm_ioremap(&pdev->dev, pdata->phys_base, pdata->size);static int msm_wdog_dt_to_pdata(struct platform_device *pdev, struct msm_watchdog_data *pdata){ struct device_node *node = pdev->dev.of_node; struct resource *res; int ret; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wdt-base"); if (!res) return -ENODEV; pdata->size = resource_size(res); pdata->phys_base = res->start; if (unlikely(!(devm_request_mem_region(&pdev->dev, pdata->phys_base, pdata->size, "msm-watchdog")))) { dev_err(&pdev->dev, "%s cannot reserve watchdog region/n", __func__); return -ENXIO; } pdata->base = devm_ioremap(&pdev->dev, pdata->phys_base, pdata->size); if (!pdata->base) { dev_err(&pdev->dev, "%s cannot map wdog register space/n", __func__); return -ENXIO; }#ifdef CONFIG_SEC_DEBUG wdog_base_addr = pdata->base;#endif res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wdt-absent-base"); if (res) { pdata->wdog_absent_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!pdata->wdog_absent_base) { dev_err(&pdev->dev, "cannot map wdog absent register space/n"); return -ENXIO; } } else { dev_info(&pdev->dev, "wdog absent resource not 下面是probe函數

static int msm_watchdog_probe(struct platform_device *pdev){ int ret; struct msm_watchdog_data *wdog_dd; wdog_wq = alloc_workqueue("wdog", WQ_HIGHPRI, 0);//初始化一個workqueue if (!wdog_wq) { pr_err("Failed to allocate watchdog workqueue/n"); return -EIO; } if (!pdev->dev.of_node || !enable) return -ENODEV; wdog_dd = kzalloc(sizeof(struct msm_watchdog_data), GFP_KERNEL); if (!wdog_dd) return -EIO; ret = msm_wdog_dt_to_pdata(pdev, wdog_dd); if (ret) goto err; wdog_data = wdog_dd; wdog_dd->dev = &pdev->dev; platform_set_drvdata(pdev, wdog_dd); cpumask_clear(&wdog_dd->alive_mask); INIT_WORK(&wdog_dd->init_dogwork_struct, init_watchdog_work); INIT_DELAYED_WORK(&wdog_dd->dogwork_struct, pet_watchdog_work); queue_work(wdog_wq, &wdog_dd->init_dogwork_struct); //上面初始化了兩個work,然后queue進去init_dogwork_struct這個work //這里queue進入是否會馬上調度執行??需要仔細看一下workqueue相關內容 return 0;err: destroy_workqueue(wdog_wq); kzfree(wdog_dd); return ret;}

初始化watchdog

static void init_watchdog_work(struct work_struct *work){ struct msm_watchdog_data *wdog_dd = container_of(work, struct msm_watchdog_data, init_dogwork_struct); unsigned long delay_time; int error; u64 timeout; int ret; /* * Disable the watchdog for cluster 1 so that cluster 0 watchdog will * be mapped to the entire sub-system. */ if (wdog_dd->wdog_absent_base) __raw_writel(2, wdog_dd->wdog_absent_base + WDOG_ABSENT); if (wdog_dd->irq_ppi) { wdog_dd->wdog_cpu_dd = alloc_percpu(struct msm_watchdog_data *); if (!wdog_dd->wdog_cpu_dd) { dev_err(wdog_dd->dev, "fail to allocate cpu data/n"); return; } *__this_cpu_ptr(wdog_dd->wdog_cpu_dd) = wdog_dd; ret = request_percpu_irq(wdog_dd->bark_irq, wdog_ppi_bark, "apps_wdog_bark", wdog_dd->wdog_cpu_dd); if (ret) { dev_err(wdog_dd->dev, "failed to request bark irq/n"); free_percpu(wdog_dd->wdog_cpu_dd); return; } } else { //給bark_irq設置回調函數。如果設定的20秒的bark時間之內沒有喂狗,就會觸發中斷 ret = devm_request_irq(wdog_dd->dev, wdog_dd->bark_irq, wdog_bark_handler, IRQF_TRIGGER_RISING, "apps_wdog_bark", wdog_dd); if (ret) { dev_err(wdog_dd->dev, "failed to request bark irq/n"); return; } } delay_time = msecs_to_jiffies(wdog_dd->pet_time); //delay_time等于10秒對應的jiffies //用這個delay_time來設置下一次pet_watchdog_work函數調用時間 wdog_dd->min_slack_ticks = UINT_MAX; wdog_dd->min_slack_ns = ULLONG_MAX; configure_bark_dump(wdog_dd); timeout = (wdog_dd->bark_time * WDT_HZ)/1000; //timeou為20秒對應的jiffies個數! __raw_writel(timeout, wdog_dd->base + WDT0_BARK_TIME); //根據timeout時間,設置bark_time寄存器 __raw_writel(timeout + 3*WDT_HZ, wdog_dd->base + WDT0_BITE_TIME); //根據timeout+3秒時間,設置bite_time,但這個沒有設置系統中斷函數,好像是沒有處理 wdog_dd->panic_blk.notifier_call = panic_wdog_handler; atomic_notifier_chain_register(&panic_notifier_list, &wdog_dd->panic_blk); mutex_init(&wdog_dd->disable_lock); //10秒后調用pet_watchdog_work函數 queue_delayed_work(wdog_wq, &wdog_dd->dogwork_struct, delay_time); __raw_writel(1, wdog_dd->base + WDT0_EN);//使能 __raw_writel(1, wdog_dd->base + WDT0_RST);//reset wdog_dd->last_pet = sched_clock(); wdog_dd->enabled = true;#ifdef CONFIG_SEC_DEBUG last_pet = wdog_dd->last_pet; sec_debug_save_last_pet(wdog_dd->last_pet);#endif error = device_create_file(wdog_dd->dev, &dev_attr_disable); if (error) dev_err(wdog_dd->dev, "cannot create sysfs attribute/n"); if (wdog_dd->irq_ppi) enable_percpu_irq(wdog_dd->bark_irq, 0); if (ipi_opt_en) cpu_pm_register_notifier(&wdog_cpu_pm_nb); dev_info(wdog_dd->dev, "MSM Watchdog Initialized/n"); return;}

喂狗的函數

static void pet_watchdog_work(struct work_struct *work){ unsigned long delay_time; struct delayed_work *delayed_work = to_delayed_work(work); struct msm_watchdog_data *wdog_dd = container_of(delayed_work, struct msm_watchdog_data, dogwork_struct); delay_time = msecs_to_jiffies(wdog_dd->pet_time); pr_info("pet_watchdog_work delay_time = %d enable = %d /n ",(unsigned int)delay_time,enable); if (enable) { if (wdog_dd->do_ipi_ping) ping_other_cpus(wdog_dd); pet_watchdog(wdog_dd);//喂狗 } /* Check again before scheduling * * Could have been changed on other cpu */ if (enable) //再設置10秒后喂狗 queue_delayed_work(wdog_wq, &wdog_dd->dogwork_struct, delay_time);}

打印了pet_watchdog_work的調用時間。queue_delayed_work延遲調用的時間沒有那么精確,但每次調用時間大概都是在10秒左右。

出現watchdog bark的時候怎么去debug

watchdog bark的出現,說明有比較高優先級的進程一直在運行,或者有頻繁的中斷發生,導致喂狗的work queue在10秒之內一直沒有辦法運行去喂狗(bark_time是20秒減去pet_time10秒)。

<4>[ 1990.647173] [1: krtccd: 143] reclaimed 1026 (swapped 1026) pages.<6>[ 1993.082536] I[0: mmcqd/0: 145] Watchdog bark! Now = 1993.082530<0>[ 1993.082594] I[0: mmcqd/0: 145] (sec_debug_set_upload_magic) 776655ee<6>[ 1993.082649] I[0: mmcqd/0: 145] sec_debug_set_qc_dload_magic: on=1<3>[ 1993.082712] I[0: mmcqd/0: 145] set_dload_mode <1> ( c01191fc )<0>[ 1993.082882] I[0: mmcqd/0: 145] (sec_debug_set_upload_cause) dba<6>[ 1993.082939] I[0: mmcqd/0: 145] Watchdog last pet at 1970.041145<6>[ 1993.082990] I[0: mmcqd/0: 145] cpu alive mask from last pet 0

上面的log里邊可以看到發生的wathcodg bark,然后打印了發生watchdog bark的時間(單位是秒)。然后也打印了上次pet的時間(Watchdog last pet at 1970.041145),已經超過了20秒。

解決這種問題,需要打印每個cpu的sched和irq的時間。而且其實只需要看1970秒之后到底發生了什么。

cpu0的sched和irq的log

cpu0的sched和irq的log只到1974秒左右。而且看cpu狀態,cpu0一直也是online狀態。

懷疑是卡在.app.soundalive pid = 6435這個進程,但看了task狀態是disksleep狀態

[ 1970.839923][ SECURE] SVC_ID = 12 CMD_ID = 2[ 1970.839938][ SECURE] SVC_ID = 12 CMD_ID = 2[ 1971.572058][ SECURE] SVC_ID = 12 CMD_ID = 2...[ 1974.161089][SCHEDULE] AudioOut_DD pid = 9483[ 1974.161099][SCHEDULE] kworker/u8:34 pid = 6390[ 1974.161104][SCHEDULE] @async_run_entr pid = -1[ 1974.161112][SCHEDULE] AudioOut_DD pid = 9483...[ 1974.226214][SCHEDULE] .app.soundalive pid = 6435//1974秒之后cpu0也沒有輸出什么log,然后直接到1993秒時間點[ 1993.073554][IRQ EXIT] irq = 240 start_time = 1993073539371 end_time = 1993073554527 elapsed_time = 15156[ 1993.073570][IRQ EXIT] irq = 240 start_time = 1993073555985 en[ 1974.226784][SCHEDULE] mmcqd/0 pid = 145d_time = 1993073570985 elapsed_time = 15000...//后面一堆全是irq 240和507//對應的handler函數是msm_tlmm_v4_handle_irq和sec_jack_detect_irq函數//而且這些中斷都是watchdog bark之前的,應該就是這些中斷的問題[ 1993.082526][IRQ EXIT] irq = 240 start_time = 1993082510985 end_time = 1993082526037 elapsed_time = 15052[ 1993.082528][ IRQ] irq = 35 fn = 0xc03fd72c en=0x80 preempt_count=0x10101 context=0xed395c8c//一直到喂狗時間的前一刻還在發生中斷

cpu1的sched和irq的log

irq 20的handle irq是handle_percpu_devid_irq函數 irq 30的handle irq是handle_fasteoi_irq()函數 這兩個irq頻繁觸發,是否是導致pet_watchdog_work無法調度的原因呢?

[ 1975.086905][ SECURE] SVC_ID = 12 CMD_ID = 2[ 1975.086922][ SECURE] SVC_ID = 12 CMD_ID = 2[ 1986.520440][ IRQ] irq = 20 fn = 0xc06b3108 en=0x80 preempt_count=0x10000 context=0xdb52dcc4[ 1986.520473][IRQ EXIT] irq = 20 start_time = 1986520439403 end_time = 1986520473153 elapsed_time = 33750... //中間一直反復出現irq 20和irq 39,可以根據fn的地址通過system.map去找到對應函數[ 1986.590443][ IRQ] irq = 20 fn = 0xc06b3108 en=0x80 preempt_count=0x10001 context=0xee609e7c[ 1986.590456][ IRQ] irq = 39 fn = 0xc06b3238 en=0x80 preempt_count=0x10101 context=0xee609dac[ 1986.590465][IRQ EXIT] irq = 39 start_time = 1986590455393 end_time = 1986590465445 elapsed_time = 10052[ 1986.590502][IRQ EXIT] irq = 20 start_time = 1986590440861 end_time = 1986590502007 elapsed_time = 61146....//一直到1993秒左右一直在反復出現irq20和irq39[ 1993.010442][ IRQ] irq = 20 fn = 0xc06b3108 en=0x80 preempt_count=0x10001 context=0xee609e7c[ 1993.010452][ IRQ] irq = 39 fn = 0xc06b3238 en=0x80 preempt_count=0x10101 context=0xee609dac[ 1993.010460][IRQ EXIT] irq = 39 start_time = 1993010451506 end_time = 1993010460360 elapsed_time = 8854[ 1993.010486][IRQ EXIT] irq = 20 start_time = 1993010440464 end_time = 1993010486089 elapsed_time = 45625 //在pet_watchdog_work之前irq已經結束,所以這個不是原因[ 1993.012658][SCHEDULE] qrngd pid = 240[ 1993.012665][SCHEDULE] swapper/1 pid = 0...

cpu2的sched和irq的log

[ 1966.060443][ IRQ] irq = 20 fn = 0xc06b3108 en=0x80 preempt_count=0x10001 context=0xed349c7c[ 1966.060488][IRQ EXIT] irq = 20 start_time = 1966060442205 end_time = 1966060488715 elapsed_time = 46510[ 1966.060505][SCHEDULE] ksoftirqd/2 pid = 16[ 1966.060526][SCHEDULE] krtccd pid = 143[ 1966.060723][SCHEDULE] migration/2 pid = 15[ 1966.061856][SCHEDULE] swapper/2 pid = 0[ 1966.061879][SCHEDULE] +pc(I:0,R:1) pid = -1//后面就沒有 log出來

cpu3的sched和irq的log

[ 1966.003495][SCHEDULE] -pc(1) pid = -1[ 1966.003533][SCHEDULE] migration/3 pid = 19[ 1966.004594][SCHEDULE] swapper/3 pid = 0[ 1966.004623][SCHEDULE] +pc(I:0,R:1) pid = -1...
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 句容市| 如东县| 环江| 南陵县| 会同县| 罗定市| 望江县| 蒲城县| 蛟河市| 龙山县| 丹阳市| 赤壁市| 云和县| 历史| 蕲春县| 察隅县| 增城市| 曲阜市| 遵义市| 许昌县| 柳州市| 新民市| 土默特右旗| 宜州市| 秭归县| 黄平县| 厦门市| 汝南县| 东丽区| 云阳县| 行唐县| 蒲城县| 津市市| 杭州市| 巍山| 绥江县| 辽中县| 临邑县| 增城市| 高密市| 洛浦县|