介绍高通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 PResent/n"); } //分别取device tree里边的interrupts = <0 3 0>, <0 4 0>;的第一个第二个 pdata->bark_irq = platform_get_irq(pdev, 0); pdata->bite_irq = platform_get_irq(pdev, 1); ret = of_property_read_u32(node, "qcom,bark-time", &pdata->bark_time); if (ret) { dev_err(&pdev->dev, "reading bark time failed/n"); return -ENXIO; } ret = of_property_read_u32(node, "qcom,pet-time", &pdata->pet_time); if (ret) { dev_err(&pdev->dev, "reading pet time failed/n"); return -ENXIO; } pdata->do_ipi_ping = of_property_read_bool(node, "qcom,ipi-ping"); if (!pdata->bark_time) { dev_err(&pdev->dev, "%s watchdog bark time not setup/n", __func__); return -ENXIO; } if (!pdata->pet_time) { dev_err(&pdev->dev, "%s watchdog pet time not setup/n", __func__); return -ENXIO; } pdata->irq_ppi = irq_is_percpu(pdata->bark_irq);//irq是否是 //percpu的这个在哪里指定?? dump_pdata(pdata); return 0;}下面是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;}打印了pet_watchdog_work的调用时间。queue_delayed_work延迟调用的时间没有那么精确,但每次调用时间大概都是在10秒左右。
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只到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//一直到喂狗时间的前一刻还在发生中断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...新闻热点
疑难解答