Lines Matching +full:wdt +full:- +full:timeout
1 // SPDX-License-Identifier: GPL-2.0
40 * enum mei_wdt_state - internal watchdog state
79 * struct mei_wdt - mei watchdog driver
88 * @timeout: watchdog current timeout
101 u16 timeout; member
109 * struct mei_mc_hdr - Management Control Command Header
124 * struct mei_wdt_start_request - watchdog start/ping
127 * @timeout: timeout value
132 u16 timeout; member
137 * struct mei_wdt_start_response - watchdog start/ping response
150 * struct mei_wdt_stop_request - watchdog stop
159 * mei_wdt_ping - send wd start/ping command
161 * @wdt: mei watchdog device
166 static int mei_wdt_ping(struct mei_wdt *wdt) in mei_wdt_ping() argument
174 req.hdr.bytecount = req_len - offsetof(struct mei_mc_hdr, subcommand); in mei_wdt_ping()
177 req.timeout = wdt->timeout; in mei_wdt_ping()
179 ret = mei_cldev_send(wdt->cldev, (u8 *)&req, req_len); in mei_wdt_ping()
187 * mei_wdt_stop - send wd stop command
189 * @wdt: mei watchdog device
194 static int mei_wdt_stop(struct mei_wdt *wdt) in mei_wdt_stop() argument
202 req.hdr.bytecount = req_len - offsetof(struct mei_mc_hdr, subcommand); in mei_wdt_stop()
206 ret = mei_cldev_send(wdt->cldev, (u8 *)&req, req_len); in mei_wdt_stop()
214 * mei_wdt_ops_start - wd start command from the watchdog core.
218 * Return: 0 on success or -ENODEV;
222 struct mei_wdt *wdt = watchdog_get_drvdata(wdd); in mei_wdt_ops_start() local
224 wdt->state = MEI_WDT_START; in mei_wdt_ops_start()
225 wdd->timeout = wdt->timeout; in mei_wdt_ops_start()
230 * mei_wdt_ops_stop - wd stop command from the watchdog core.
238 struct mei_wdt *wdt = watchdog_get_drvdata(wdd); in mei_wdt_ops_stop() local
241 if (wdt->state != MEI_WDT_RUNNING) in mei_wdt_ops_stop()
244 wdt->state = MEI_WDT_STOPPING; in mei_wdt_ops_stop()
246 ret = mei_wdt_stop(wdt); in mei_wdt_ops_stop()
250 wdt->state = MEI_WDT_IDLE; in mei_wdt_ops_stop()
256 * mei_wdt_ops_ping - wd ping command from the watchdog core.
264 struct mei_wdt *wdt = watchdog_get_drvdata(wdd); in mei_wdt_ops_ping() local
267 if (wdt->state != MEI_WDT_START && wdt->state != MEI_WDT_RUNNING) in mei_wdt_ops_ping()
270 if (wdt->resp_required) in mei_wdt_ops_ping()
271 init_completion(&wdt->response); in mei_wdt_ops_ping()
273 wdt->state = MEI_WDT_RUNNING; in mei_wdt_ops_ping()
274 ret = mei_wdt_ping(wdt); in mei_wdt_ops_ping()
278 if (wdt->resp_required) in mei_wdt_ops_ping()
279 ret = wait_for_completion_killable(&wdt->response); in mei_wdt_ops_ping()
285 * mei_wdt_ops_set_timeout - wd set timeout command from the watchdog core.
288 * @timeout: timeout value to set
293 unsigned int timeout) in mei_wdt_ops_set_timeout() argument
296 struct mei_wdt *wdt = watchdog_get_drvdata(wdd); in mei_wdt_ops_set_timeout() local
299 wdt->timeout = timeout; in mei_wdt_ops_set_timeout()
300 wdd->timeout = timeout; in mei_wdt_ops_set_timeout()
322 * __mei_wdt_is_registered - check if wdt is registered
324 * @wdt: mei watchdog device
326 * Return: true if the wdt is registered with the watchdog subsystem
327 * Locking: should be called under wdt->reg_lock
329 static inline bool __mei_wdt_is_registered(struct mei_wdt *wdt) in __mei_wdt_is_registered() argument
331 return !!watchdog_get_drvdata(&wdt->wdd); in __mei_wdt_is_registered()
335 * mei_wdt_unregister - unregister from the watchdog subsystem
337 * @wdt: mei watchdog device
339 static void mei_wdt_unregister(struct mei_wdt *wdt) in mei_wdt_unregister() argument
341 mutex_lock(&wdt->reg_lock); in mei_wdt_unregister()
343 if (__mei_wdt_is_registered(wdt)) { in mei_wdt_unregister()
344 watchdog_unregister_device(&wdt->wdd); in mei_wdt_unregister()
345 watchdog_set_drvdata(&wdt->wdd, NULL); in mei_wdt_unregister()
346 memset(&wdt->wdd, 0, sizeof(wdt->wdd)); in mei_wdt_unregister()
349 mutex_unlock(&wdt->reg_lock); in mei_wdt_unregister()
353 * mei_wdt_register - register with the watchdog subsystem
355 * @wdt: mei watchdog device
359 static int mei_wdt_register(struct mei_wdt *wdt) in mei_wdt_register() argument
364 if (!wdt || !wdt->cldev) in mei_wdt_register()
365 return -EINVAL; in mei_wdt_register()
367 dev = &wdt->cldev->dev; in mei_wdt_register()
369 mutex_lock(&wdt->reg_lock); in mei_wdt_register()
371 if (__mei_wdt_is_registered(wdt)) { in mei_wdt_register()
376 wdt->wdd.info = &wd_info; in mei_wdt_register()
377 wdt->wdd.ops = &wd_ops; in mei_wdt_register()
378 wdt->wdd.parent = dev; in mei_wdt_register()
379 wdt->wdd.timeout = MEI_WDT_DEFAULT_TIMEOUT; in mei_wdt_register()
380 wdt->wdd.min_timeout = MEI_WDT_MIN_TIMEOUT; in mei_wdt_register()
381 wdt->wdd.max_timeout = MEI_WDT_MAX_TIMEOUT; in mei_wdt_register()
383 watchdog_set_drvdata(&wdt->wdd, wdt); in mei_wdt_register()
384 watchdog_stop_on_reboot(&wdt->wdd); in mei_wdt_register()
385 watchdog_stop_on_unregister(&wdt->wdd); in mei_wdt_register()
387 ret = watchdog_register_device(&wdt->wdd); in mei_wdt_register()
389 watchdog_set_drvdata(&wdt->wdd, NULL); in mei_wdt_register()
391 wdt->state = MEI_WDT_IDLE; in mei_wdt_register()
394 mutex_unlock(&wdt->reg_lock); in mei_wdt_register()
400 struct mei_wdt *wdt = container_of(work, struct mei_wdt, unregister); in mei_wdt_unregister_work() local
402 mei_wdt_unregister(wdt); in mei_wdt_unregister_work()
406 * mei_wdt_rx - callback for data receive
412 struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); in mei_wdt_rx() local
417 ret = mei_cldev_recv(wdt->cldev, (u8 *)&res, res_len); in mei_wdt_rx()
419 dev_err(&cldev->dev, "failure in recv %d\n", ret); in mei_wdt_rx()
428 dev_err(&cldev->dev, "recv small data %d\n", ret); in mei_wdt_rx()
434 dev_err(&cldev->dev, "wrong command received\n"); in mei_wdt_rx()
439 dev_warn(&cldev->dev, "unsupported command %d :%s[%d]\n", in mei_wdt_rx()
441 mei_wdt_state_str(wdt->state), in mei_wdt_rx()
442 wdt->state); in mei_wdt_rx()
450 if (wdt->state == MEI_WDT_RUNNING) { in mei_wdt_rx()
452 wdt->state = MEI_WDT_NOT_REQUIRED; in mei_wdt_rx()
453 schedule_work(&wdt->unregister); in mei_wdt_rx()
458 if (wdt->state == MEI_WDT_PROBE) { in mei_wdt_rx()
460 wdt->state = MEI_WDT_NOT_REQUIRED; in mei_wdt_rx()
463 mei_wdt_stop(wdt); in mei_wdt_rx()
464 mei_wdt_register(wdt); in mei_wdt_rx()
469 dev_warn(&cldev->dev, "not in correct state %s[%d]\n", in mei_wdt_rx()
470 mei_wdt_state_str(wdt->state), wdt->state); in mei_wdt_rx()
473 if (!completion_done(&wdt->response)) in mei_wdt_rx()
474 complete(&wdt->response); in mei_wdt_rx()
478 * mei_wdt_notif - callback for event notification
484 struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); in mei_wdt_notif() local
486 if (wdt->state != MEI_WDT_NOT_REQUIRED) in mei_wdt_notif()
489 mei_wdt_register(wdt); in mei_wdt_notif()
497 struct mei_wdt *wdt = file->private_data; in mei_dbgfs_read_activation() local
502 mutex_lock(&wdt->reg_lock); in mei_dbgfs_read_activation()
504 __mei_wdt_is_registered(wdt) ? "activated" : "deactivated"); in mei_dbgfs_read_activation()
505 mutex_unlock(&wdt->reg_lock); in mei_dbgfs_read_activation()
519 struct mei_wdt *wdt = file->private_data; in mei_dbgfs_read_state() local
524 mei_wdt_state_str(wdt->state)); in mei_dbgfs_read_state()
535 static void dbgfs_unregister(struct mei_wdt *wdt) in dbgfs_unregister() argument
537 debugfs_remove_recursive(wdt->dbgfs_dir); in dbgfs_unregister()
538 wdt->dbgfs_dir = NULL; in dbgfs_unregister()
541 static void dbgfs_register(struct mei_wdt *wdt) in dbgfs_register() argument
546 wdt->dbgfs_dir = dir; in dbgfs_register()
548 debugfs_create_file("state", S_IRUSR, dir, wdt, &dbgfs_fops_state); in dbgfs_register()
550 debugfs_create_file("activation", S_IRUSR, dir, wdt, in dbgfs_register()
556 static inline void dbgfs_unregister(struct mei_wdt *wdt) {} in dbgfs_unregister() argument
557 static inline void dbgfs_register(struct mei_wdt *wdt) {} in dbgfs_register() argument
563 struct mei_wdt *wdt; in mei_wdt_probe() local
566 wdt = kzalloc(sizeof(struct mei_wdt), GFP_KERNEL); in mei_wdt_probe()
567 if (!wdt) in mei_wdt_probe()
568 return -ENOMEM; in mei_wdt_probe()
570 wdt->timeout = MEI_WDT_DEFAULT_TIMEOUT; in mei_wdt_probe()
571 wdt->state = MEI_WDT_PROBE; in mei_wdt_probe()
572 wdt->cldev = cldev; in mei_wdt_probe()
573 wdt->resp_required = mei_cldev_ver(cldev) > 0x1; in mei_wdt_probe()
574 mutex_init(&wdt->reg_lock); in mei_wdt_probe()
575 init_completion(&wdt->response); in mei_wdt_probe()
576 INIT_WORK(&wdt->unregister, mei_wdt_unregister_work); in mei_wdt_probe()
578 mei_cldev_set_drvdata(cldev, wdt); in mei_wdt_probe()
582 dev_err(&cldev->dev, "Could not enable cl device\n"); in mei_wdt_probe()
586 ret = mei_cldev_register_rx_cb(wdt->cldev, mei_wdt_rx); in mei_wdt_probe()
588 dev_err(&cldev->dev, "Could not reg rx event ret=%d\n", ret); in mei_wdt_probe()
592 ret = mei_cldev_register_notif_cb(wdt->cldev, mei_wdt_notif); in mei_wdt_probe()
595 if (ret && ret != -EOPNOTSUPP) { in mei_wdt_probe()
596 dev_err(&cldev->dev, "Could not reg notif event ret=%d\n", ret); in mei_wdt_probe()
602 if (wdt->resp_required) in mei_wdt_probe()
603 ret = mei_wdt_ping(wdt); in mei_wdt_probe()
605 ret = mei_wdt_register(wdt); in mei_wdt_probe()
610 dbgfs_register(wdt); in mei_wdt_probe()
618 kfree(wdt); in mei_wdt_probe()
625 struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); in mei_wdt_remove() local
628 if (!completion_done(&wdt->response)) in mei_wdt_remove()
629 complete(&wdt->response); in mei_wdt_remove()
631 cancel_work_sync(&wdt->unregister); in mei_wdt_remove()
633 mei_wdt_unregister(wdt); in mei_wdt_remove()
637 dbgfs_unregister(wdt); in mei_wdt_remove()
639 kfree(wdt); in mei_wdt_remove()