Message ID | 1618992304-18903-1-git-send-email-wangqing@vivo.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | [V5] watchdog: mtk: support dual mode when the bark irq is available | expand |
Hi Wang, Thank you for the patch! Yet something to improve: [auto build test ERROR on hwmon/hwmon-next] [also build test ERROR on soc/for-next linus/master v5.12-rc8 next-20210420] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Wang-Qing/watchdog-mtk-support-dual-mode-when-the-bark-irq-is-available/20210421-160730 base: https://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git hwmon-next config: mips-randconfig-r031-20210421 (attached as .config) compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project d87b9b81ccb95217181ce75515c6c68bbb408ca4) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install mips cross compiling tool for clang build # apt-get install binutils-mips-linux-gnu # https://github.com/0day-ci/linux/commit/bb28c4d8391120b54c691e2407dae46761ef69af git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Wang-Qing/watchdog-mtk-support-dual-mode-when-the-bark-irq-is-available/20210421-160730 git checkout bb28c4d8391120b54c691e2407dae46761ef69af # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=mips If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All error/warnings (new ones prefixed by >>): >> drivers/watchdog/mtk_wdt.c:327:16: warning: missing terminating '"' character [-Winvalid-pp-token] dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d, ^ >> drivers/watchdog/mtk_wdt.c:327:16: error: expected expression drivers/watchdog/mtk_wdt.c:328:19: warning: missing terminating '"' character [-Winvalid-pp-token] dual_mode=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout, dual_mode); ^ 2 warnings and 1 error generated. vim +327 drivers/watchdog/mtk_wdt.c 276 277 static int mtk_wdt_probe(struct platform_device *pdev) 278 { 279 struct device *dev = &pdev->dev; 280 struct mtk_wdt_dev *mtk_wdt; 281 const struct mtk_wdt_data *wdt_data; 282 int err, irq; 283 284 mtk_wdt = devm_kzalloc(dev, sizeof(*mtk_wdt), GFP_KERNEL); 285 if (!mtk_wdt) 286 return -ENOMEM; 287 288 platform_set_drvdata(pdev, mtk_wdt); 289 290 mtk_wdt->wdt_base = devm_platform_ioremap_resource(pdev, 0); 291 if (IS_ERR(mtk_wdt->wdt_base)) 292 return PTR_ERR(mtk_wdt->wdt_base); 293 294 if (dual_mode) { 295 irq = platform_get_irq(pdev, 0); 296 if (irq > 0) { 297 err = devm_request_irq(&pdev->dev, irq, mtk_wdt_isr, 0, "wdt_bark", 298 &mtk_wdt->wdt_dev); 299 if (err) 300 return err; 301 } else { 302 dual_mode = 0; 303 dev_info(&pdev->dev, "couldn't get wdt irq, set dual_mode = 0\n"); 304 } 305 } 306 307 mtk_wdt->wdt_dev.info = &mtk_wdt_info; 308 mtk_wdt->wdt_dev.ops = &mtk_wdt_ops; 309 mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT; 310 mtk_wdt->wdt_dev.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT * 1000; 311 mtk_wdt->wdt_dev.min_timeout = WDT_MIN_TIMEOUT; 312 mtk_wdt->wdt_dev.parent = dev; 313 314 watchdog_init_timeout(&mtk_wdt->wdt_dev, timeout, dev); 315 watchdog_set_nowayout(&mtk_wdt->wdt_dev, nowayout); 316 watchdog_set_restart_priority(&mtk_wdt->wdt_dev, 128); 317 318 watchdog_set_drvdata(&mtk_wdt->wdt_dev, mtk_wdt); 319 320 mtk_wdt_init(&mtk_wdt->wdt_dev); 321 322 watchdog_stop_on_reboot(&mtk_wdt->wdt_dev); 323 err = devm_watchdog_register_device(dev, &mtk_wdt->wdt_dev); 324 if (unlikely(err)) 325 return err; 326 > 327 dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d, 328 dual_mode=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout, dual_mode); 329 330 wdt_data = of_device_get_match_data(dev); 331 if (wdt_data) { 332 err = toprgu_register_reset_controller(pdev, 333 wdt_data->toprgu_sw_rst_num); 334 if (err) 335 return err; 336 } 337 return 0; 338 } 339 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Hi Wang, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on hwmon/hwmon-next] [also build test WARNING on soc/for-next linus/master v5.12-rc8 next-20210420] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Wang-Qing/watchdog-mtk-support-dual-mode-when-the-bark-irq-is-available/20210421-160730 base: https://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git hwmon-next config: arc-allyesconfig (attached as .config) compiler: arceb-elf-gcc (GCC) 9.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/bb28c4d8391120b54c691e2407dae46761ef69af git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Wang-Qing/watchdog-mtk-support-dual-mode-when-the-bark-irq-is-available/20210421-160730 git checkout bb28c4d8391120b54c691e2407dae46761ef69af # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross W=1 ARCH=arc If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): drivers/watchdog/mtk_wdt.c: In function 'mtk_wdt_probe': >> drivers/watchdog/mtk_wdt.c:327:16: warning: missing terminating " character 327 | dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d, | ^ In file included from include/linux/device.h:15, from include/linux/node.h:18, from include/linux/cpu.h:17, from include/linux/of_device.h:5, from drivers/watchdog/mtk_wdt.c:23: drivers/watchdog/mtk_wdt.c:327:16: error: missing terminating " character 327 | dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/dev_printk.h:19:22: note: in definition of macro 'dev_fmt' 19 | #define dev_fmt(fmt) fmt | ^~~ drivers/watchdog/mtk_wdt.c:327:2: note: in expansion of macro 'dev_info' 327 | dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d, | ^~~~~~~~ drivers/watchdog/mtk_wdt.c:328:14: error: expected expression before '%' token 328 | dual_mode=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout, dual_mode); | ^ include/linux/dev_printk.h:19:22: note: in definition of macro 'dev_fmt' 19 | #define dev_fmt(fmt) fmt | ^~~ drivers/watchdog/mtk_wdt.c:327:2: note: in expansion of macro 'dev_info' 327 | dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d, | ^~~~~~~~ drivers/watchdog/mtk_wdt.c:328:17: error: stray '\' in program 328 | dual_mode=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout, dual_mode); | ^ drivers/watchdog/mtk_wdt.c:328:18: error: expected ';' before 'n' 328 | dual_mode=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout, dual_mode); | ^ drivers/watchdog/mtk_wdt.c:328:19: warning: missing terminating " character 328 | dual_mode=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout, dual_mode); | ^ drivers/watchdog/mtk_wdt.c:328:19: error: missing terminating " character 328 | dual_mode=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout, dual_mode); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ vim +327 drivers/watchdog/mtk_wdt.c 276 277 static int mtk_wdt_probe(struct platform_device *pdev) 278 { 279 struct device *dev = &pdev->dev; 280 struct mtk_wdt_dev *mtk_wdt; 281 const struct mtk_wdt_data *wdt_data; 282 int err, irq; 283 284 mtk_wdt = devm_kzalloc(dev, sizeof(*mtk_wdt), GFP_KERNEL); 285 if (!mtk_wdt) 286 return -ENOMEM; 287 288 platform_set_drvdata(pdev, mtk_wdt); 289 290 mtk_wdt->wdt_base = devm_platform_ioremap_resource(pdev, 0); 291 if (IS_ERR(mtk_wdt->wdt_base)) 292 return PTR_ERR(mtk_wdt->wdt_base); 293 294 if (dual_mode) { 295 irq = platform_get_irq(pdev, 0); 296 if (irq > 0) { 297 err = devm_request_irq(&pdev->dev, irq, mtk_wdt_isr, 0, "wdt_bark", 298 &mtk_wdt->wdt_dev); 299 if (err) 300 return err; 301 } else { 302 dual_mode = 0; 303 dev_info(&pdev->dev, "couldn't get wdt irq, set dual_mode = 0\n"); 304 } 305 } 306 307 mtk_wdt->wdt_dev.info = &mtk_wdt_info; 308 mtk_wdt->wdt_dev.ops = &mtk_wdt_ops; 309 mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT; 310 mtk_wdt->wdt_dev.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT * 1000; 311 mtk_wdt->wdt_dev.min_timeout = WDT_MIN_TIMEOUT; 312 mtk_wdt->wdt_dev.parent = dev; 313 314 watchdog_init_timeout(&mtk_wdt->wdt_dev, timeout, dev); 315 watchdog_set_nowayout(&mtk_wdt->wdt_dev, nowayout); 316 watchdog_set_restart_priority(&mtk_wdt->wdt_dev, 128); 317 318 watchdog_set_drvdata(&mtk_wdt->wdt_dev, mtk_wdt); 319 320 mtk_wdt_init(&mtk_wdt->wdt_dev); 321 322 watchdog_stop_on_reboot(&mtk_wdt->wdt_dev); 323 err = devm_watchdog_register_device(dev, &mtk_wdt->wdt_dev); 324 if (unlikely(err)) 325 return err; 326 > 327 dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d, 328 dual_mode=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout, dual_mode); 329 330 wdt_data = of_device_get_match_data(dev); 331 if (wdt_data) { 332 err = toprgu_register_reset_controller(pdev, 333 wdt_data->toprgu_sw_rst_num); 334 if (err) 335 return err; 336 } 337 return 0; 338 } 339 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
On 4/21/21 1:05 AM, Wang Qing wrote: > Support using irq handling wdt bark first instead of directly resetting. > > When the watchdog timer expires in dual mode, an interrupt will be > triggered first, then the timing restarts. The reset signal will be > initiated when the timer expires again. > > The dual mode is disabled by default. > This means the real timeout is now timeout * 2. This is not what is supposed to happen. The hard watchdog timeout needs to happen at 'timeout'. If you want to do this, it needs to be done using pre-timeout, only the pre-timeout time (and thus the watchdog timeout written into the chip) must be limited to timeout / 2. Pre-timeout must by default be disabled and only be supported if an interrupt was provided. I don't see a need for an additional module parameter. Providing an interrupt implies that pre-timeout support is wanted. This needs to be documented accordingly. I am not lot looking at the errors reported by 0-day. Please address those. Guenter > V2: > - panic() by default if WATCHDOG_PRETIMEOUT_GOV is not enabled. > > V3: > - Modify the pretimeout behavior, manually reset after the pretimeout > - is processed and wait until timeout. > > V4: > - Remove pretimeout related processing. > - Add dual mode control separately. > > V5: > - Fix some formatting and printing problems. > > Signed-off-by: Wang Qing <wangqing@vivo.com> > --- > drivers/watchdog/mtk_wdt.c | 36 ++++++++++++++++++++++++++++++++---- > 1 file changed, 32 insertions(+), 4 deletions(-) > > diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c > index 97ca993..40122f8 > --- a/drivers/watchdog/mtk_wdt.c > +++ b/drivers/watchdog/mtk_wdt.c > @@ -25,6 +25,7 @@ > #include <linux/reset-controller.h> > #include <linux/types.h> > #include <linux/watchdog.h> > +#include <linux/interrupt.h> > > #define WDT_MAX_TIMEOUT 31 > #define WDT_MIN_TIMEOUT 1 > @@ -57,6 +58,7 @@ > > static bool nowayout = WATCHDOG_NOWAYOUT; > static unsigned int timeout; > +static bool dual_mode; > > struct mtk_wdt_dev { > struct watchdog_device wdt_dev; > @@ -239,13 +241,23 @@ static int mtk_wdt_start(struct watchdog_device *wdt_dev) > return ret; > > reg = ioread32(wdt_base + WDT_MODE); > - reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); > + if (dual_mode) > + reg |= (WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); > + else > + reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); > reg |= (WDT_MODE_EN | WDT_MODE_KEY); > iowrite32(reg, wdt_base + WDT_MODE); > > return 0; > } > > +static irqreturn_t mtk_wdt_isr(int irq, void *arg) > +{ > + panic("wdt bark!\n"); > + > + return IRQ_HANDLED; > +} > + > static const struct watchdog_info mtk_wdt_info = { > .identity = DRV_NAME, > .options = WDIOF_SETTIMEOUT | > @@ -267,7 +279,7 @@ static int mtk_wdt_probe(struct platform_device *pdev) > struct device *dev = &pdev->dev; > struct mtk_wdt_dev *mtk_wdt; > const struct mtk_wdt_data *wdt_data; > - int err; > + int err, irq; > > mtk_wdt = devm_kzalloc(dev, sizeof(*mtk_wdt), GFP_KERNEL); > if (!mtk_wdt) > @@ -279,6 +291,19 @@ static int mtk_wdt_probe(struct platform_device *pdev) > if (IS_ERR(mtk_wdt->wdt_base)) > return PTR_ERR(mtk_wdt->wdt_base); > > + if (dual_mode) { > + irq = platform_get_irq(pdev, 0); > + if (irq > 0) { > + err = devm_request_irq(&pdev->dev, irq, mtk_wdt_isr, 0, "wdt_bark", > + &mtk_wdt->wdt_dev); > + if (err) > + return err; > + } else { > + dual_mode = 0; > + dev_info(&pdev->dev, "couldn't get wdt irq, set dual_mode = 0\n"); > + } > + } > + > mtk_wdt->wdt_dev.info = &mtk_wdt_info; > mtk_wdt->wdt_dev.ops = &mtk_wdt_ops; > mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT; > @@ -299,8 +324,8 @@ static int mtk_wdt_probe(struct platform_device *pdev) > if (unlikely(err)) > return err; > > - dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n", > - mtk_wdt->wdt_dev.timeout, nowayout); > + dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d, > + dual_mode=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout, dual_mode); > > wdt_data = of_device_get_match_data(dev); > if (wdt_data) { > @@ -368,6 +393,9 @@ module_param(nowayout, bool, 0); > MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" > __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); > > +module_param(dual_mode, bool, 0); > +MODULE_PARM_DESC(dual_mode, "Dual mode triggers irq before reset (default=0)"); > + > MODULE_LICENSE("GPL"); > MODULE_AUTHOR("Matthias Brugger <matthias.bgg@gmail.com>"); > MODULE_DESCRIPTION("Mediatek WatchDog Timer Driver"); >
Hi Wang, Thank you for the patch! Yet something to improve: [auto build test ERROR on hwmon/hwmon-next] [also build test ERROR on soc/for-next linus/master v5.12-rc8 next-20210421] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Wang-Qing/watchdog-mtk-support-dual-mode-when-the-bark-irq-is-available/20210421-160730 base: https://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git hwmon-next config: nds32-randconfig-r021-20210421 (attached as .config) compiler: nds32le-linux-gcc (GCC) 9.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/bb28c4d8391120b54c691e2407dae46761ef69af git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Wang-Qing/watchdog-mtk-support-dual-mode-when-the-bark-irq-is-available/20210421-160730 git checkout bb28c4d8391120b54c691e2407dae46761ef69af # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross W=1 ARCH=nds32 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): In file included from include/linux/sched.h:12, from include/linux/ptrace.h:6, from include/uapi/asm-generic/bpf_perf_event.h:4, from ./arch/nds32/include/generated/uapi/asm/bpf_perf_event.h:1, from include/uapi/linux/bpf_perf_event.h:11, from include/linux/perf_event.h:18, from arch/nds32/kernel/perf_event_cpu.c:9: arch/nds32/kernel/perf_event_cpu.c: In function 'unwind_frame_kernel': >> arch/nds32/include/asm/current.h:10:13: error: '$r25' undeclared (first use in this function) 10 | #define tsk $r25 | ^~~~ arch/nds32/kernel/perf_event_cpu.c:1255:8: note: in expansion of macro 'tsk' 1255 | (tsk, &graph, frame->lp, NULL); | ^~~ arch/nds32/include/asm/current.h:10:13: note: each undeclared identifier is reported only once for each function it appears in 10 | #define tsk $r25 | ^~~~ arch/nds32/kernel/perf_event_cpu.c:1255:8: note: in expansion of macro 'tsk' 1255 | (tsk, &graph, frame->lp, NULL); | ^~~ arch/nds32/kernel/perf_event_cpu.c:1257:13: warning: assignment to 'long unsigned int' from 'long unsigned int *' makes integer from pointer without a cast [-Wint-conversion] 1257 | frame->sp = ((unsigned long *)frame->sp) + 1; | ^ -- drivers/watchdog/mtk_wdt.c: In function 'mtk_wdt_probe': drivers/watchdog/mtk_wdt.c:327:16: warning: missing terminating " character 327 | dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d, | ^ In file included from include/linux/device.h:15, from include/linux/node.h:18, from include/linux/cpu.h:17, from include/linux/of_device.h:5, from drivers/watchdog/mtk_wdt.c:23: >> drivers/watchdog/mtk_wdt.c:327:16: error: missing terminating " character 327 | dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/dev_printk.h:19:22: note: in definition of macro 'dev_fmt' 19 | #define dev_fmt(fmt) fmt | ^~~ drivers/watchdog/mtk_wdt.c:327:2: note: in expansion of macro 'dev_info' 327 | dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d, | ^~~~~~~~ >> drivers/watchdog/mtk_wdt.c:328:14: error: expected expression before '%' token 328 | dual_mode=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout, dual_mode); | ^ include/linux/dev_printk.h:19:22: note: in definition of macro 'dev_fmt' 19 | #define dev_fmt(fmt) fmt | ^~~ drivers/watchdog/mtk_wdt.c:327:2: note: in expansion of macro 'dev_info' 327 | dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d, | ^~~~~~~~ drivers/watchdog/mtk_wdt.c:328:17: error: stray '\' in program 328 | dual_mode=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout, dual_mode); | ^ >> drivers/watchdog/mtk_wdt.c:328:18: error: expected ';' before 'n' 328 | dual_mode=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout, dual_mode); | ^ drivers/watchdog/mtk_wdt.c:328:19: warning: missing terminating " character 328 | dual_mode=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout, dual_mode); | ^ drivers/watchdog/mtk_wdt.c:328:19: error: missing terminating " character 328 | dual_mode=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout, dual_mode); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ vim +327 drivers/watchdog/mtk_wdt.c 276 277 static int mtk_wdt_probe(struct platform_device *pdev) 278 { 279 struct device *dev = &pdev->dev; 280 struct mtk_wdt_dev *mtk_wdt; 281 const struct mtk_wdt_data *wdt_data; 282 int err, irq; 283 284 mtk_wdt = devm_kzalloc(dev, sizeof(*mtk_wdt), GFP_KERNEL); 285 if (!mtk_wdt) 286 return -ENOMEM; 287 288 platform_set_drvdata(pdev, mtk_wdt); 289 290 mtk_wdt->wdt_base = devm_platform_ioremap_resource(pdev, 0); 291 if (IS_ERR(mtk_wdt->wdt_base)) 292 return PTR_ERR(mtk_wdt->wdt_base); 293 294 if (dual_mode) { 295 irq = platform_get_irq(pdev, 0); 296 if (irq > 0) { 297 err = devm_request_irq(&pdev->dev, irq, mtk_wdt_isr, 0, "wdt_bark", 298 &mtk_wdt->wdt_dev); 299 if (err) 300 return err; 301 } else { 302 dual_mode = 0; 303 dev_info(&pdev->dev, "couldn't get wdt irq, set dual_mode = 0\n"); 304 } 305 } 306 307 mtk_wdt->wdt_dev.info = &mtk_wdt_info; 308 mtk_wdt->wdt_dev.ops = &mtk_wdt_ops; 309 mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT; 310 mtk_wdt->wdt_dev.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT * 1000; 311 mtk_wdt->wdt_dev.min_timeout = WDT_MIN_TIMEOUT; 312 mtk_wdt->wdt_dev.parent = dev; 313 314 watchdog_init_timeout(&mtk_wdt->wdt_dev, timeout, dev); 315 watchdog_set_nowayout(&mtk_wdt->wdt_dev, nowayout); 316 watchdog_set_restart_priority(&mtk_wdt->wdt_dev, 128); 317 318 watchdog_set_drvdata(&mtk_wdt->wdt_dev, mtk_wdt); 319 320 mtk_wdt_init(&mtk_wdt->wdt_dev); 321 322 watchdog_stop_on_reboot(&mtk_wdt->wdt_dev); 323 err = devm_watchdog_register_device(dev, &mtk_wdt->wdt_dev); 324 if (unlikely(err)) 325 return err; 326 > 327 dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d, > 328 dual_mode=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout, dual_mode); 329 330 wdt_data = of_device_get_match_data(dev); 331 if (wdt_data) { 332 err = toprgu_register_reset_controller(pdev, 333 wdt_data->toprgu_sw_rst_num); 334 if (err) 335 return err; 336 } 337 return 0; 338 } 339 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index 97ca993..40122f8 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -25,6 +25,7 @@ #include <linux/reset-controller.h> #include <linux/types.h> #include <linux/watchdog.h> +#include <linux/interrupt.h> #define WDT_MAX_TIMEOUT 31 #define WDT_MIN_TIMEOUT 1 @@ -57,6 +58,7 @@ static bool nowayout = WATCHDOG_NOWAYOUT; static unsigned int timeout; +static bool dual_mode; struct mtk_wdt_dev { struct watchdog_device wdt_dev; @@ -239,13 +241,23 @@ static int mtk_wdt_start(struct watchdog_device *wdt_dev) return ret; reg = ioread32(wdt_base + WDT_MODE); - reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); + if (dual_mode) + reg |= (WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); + else + reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); reg |= (WDT_MODE_EN | WDT_MODE_KEY); iowrite32(reg, wdt_base + WDT_MODE); return 0; } +static irqreturn_t mtk_wdt_isr(int irq, void *arg) +{ + panic("wdt bark!\n"); + + return IRQ_HANDLED; +} + static const struct watchdog_info mtk_wdt_info = { .identity = DRV_NAME, .options = WDIOF_SETTIMEOUT | @@ -267,7 +279,7 @@ static int mtk_wdt_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct mtk_wdt_dev *mtk_wdt; const struct mtk_wdt_data *wdt_data; - int err; + int err, irq; mtk_wdt = devm_kzalloc(dev, sizeof(*mtk_wdt), GFP_KERNEL); if (!mtk_wdt) @@ -279,6 +291,19 @@ static int mtk_wdt_probe(struct platform_device *pdev) if (IS_ERR(mtk_wdt->wdt_base)) return PTR_ERR(mtk_wdt->wdt_base); + if (dual_mode) { + irq = platform_get_irq(pdev, 0); + if (irq > 0) { + err = devm_request_irq(&pdev->dev, irq, mtk_wdt_isr, 0, "wdt_bark", + &mtk_wdt->wdt_dev); + if (err) + return err; + } else { + dual_mode = 0; + dev_info(&pdev->dev, "couldn't get wdt irq, set dual_mode = 0\n"); + } + } + mtk_wdt->wdt_dev.info = &mtk_wdt_info; mtk_wdt->wdt_dev.ops = &mtk_wdt_ops; mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT; @@ -299,8 +324,8 @@ static int mtk_wdt_probe(struct platform_device *pdev) if (unlikely(err)) return err; - dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n", - mtk_wdt->wdt_dev.timeout, nowayout); + dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d, + dual_mode=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout, dual_mode); wdt_data = of_device_get_match_data(dev); if (wdt_data) { @@ -368,6 +393,9 @@ module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +module_param(dual_mode, bool, 0); +MODULE_PARM_DESC(dual_mode, "Dual mode triggers irq before reset (default=0)"); + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Matthias Brugger <matthias.bgg@gmail.com>"); MODULE_DESCRIPTION("Mediatek WatchDog Timer Driver");
Support using irq handling wdt bark first instead of directly resetting. When the watchdog timer expires in dual mode, an interrupt will be triggered first, then the timing restarts. The reset signal will be initiated when the timer expires again. The dual mode is disabled by default. V2: - panic() by default if WATCHDOG_PRETIMEOUT_GOV is not enabled. V3: - Modify the pretimeout behavior, manually reset after the pretimeout - is processed and wait until timeout. V4: - Remove pretimeout related processing. - Add dual mode control separately. V5: - Fix some formatting and printing problems. Signed-off-by: Wang Qing <wangqing@vivo.com> --- drivers/watchdog/mtk_wdt.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-)