/** * enum mei_wdt_state - internal watchdog state * * @MEI_WDT_PROBE: wd in probing stage * @MEI_WDT_IDLE: wd is idle and not opened * @MEI_WDT_START: wd was opened, start was called * @MEI_WDT_RUNNING: wd is expecting keep alive pings * @MEI_WDT_STOPPING: wd is stopping and will move to IDLE * @MEI_WDT_NOT_REQUIRED: wd device is not required
*/ enum mei_wdt_state {
MEI_WDT_PROBE,
MEI_WDT_IDLE,
MEI_WDT_START,
MEI_WDT_RUNNING,
MEI_WDT_STOPPING,
MEI_WDT_NOT_REQUIRED,
};
staticconstchar *mei_wdt_state_str(enum mei_wdt_state state)
{ switch (state) { case MEI_WDT_PROBE: return"PROBE"; case MEI_WDT_IDLE: return"IDLE"; case MEI_WDT_START: return"START"; case MEI_WDT_RUNNING: return"RUNNING"; case MEI_WDT_STOPPING: return"STOPPING"; case MEI_WDT_NOT_REQUIRED: return"NOT_REQUIRED"; default: return"unknown";
}
}
/** * struct mei_mc_hdr - Management Control Command Header * * @command: Management Control (0x2) * @bytecount: Number of bytes in the message beyond this byte * @subcommand: Management Control Subcommand * @versionnumber: Management Control Version (0x10)
*/ struct mei_mc_hdr {
u8 command;
u8 bytecount;
u8 subcommand;
u8 versionnumber;
};
/* not const as the firmware_version field need to be retrieved */ staticstruct watchdog_info wd_info = {
.identity = INTEL_AMT_WATCHDOG_ID,
.options = WDIOF_KEEPALIVEPING |
WDIOF_SETTIMEOUT |
WDIOF_ALARMONLY,
};
/** * __mei_wdt_is_registered - check if wdt is registered * * @wdt: mei watchdog device * * Return: true if the wdt is registered with the watchdog subsystem * Locking: should be called under wdt->reg_lock
*/ staticinlinebool __mei_wdt_is_registered(struct mei_wdt *wdt)
{ return !!watchdog_get_drvdata(&wdt->wdd);
}
/** * mei_wdt_unregister - unregister from the watchdog subsystem * * @wdt: mei watchdog device
*/ staticvoid mei_wdt_unregister(struct mei_wdt *wdt)
{
mutex_lock(&wdt->reg_lock);
if (__mei_wdt_is_registered(wdt)) {
watchdog_unregister_device(&wdt->wdd);
watchdog_set_drvdata(&wdt->wdd, NULL);
memset(&wdt->wdd, 0, sizeof(wdt->wdd));
}
mutex_unlock(&wdt->reg_lock);
}
/** * mei_wdt_register - register with the watchdog subsystem * * @wdt: mei watchdog device * * Return: 0 if success, negative errno code for failure
*/ staticint mei_wdt_register(struct mei_wdt *wdt)
{ struct device *dev; int ret;
if (!wdt || !wdt->cldev) return -EINVAL;
dev = &wdt->cldev->dev;
mutex_lock(&wdt->reg_lock);
if (__mei_wdt_is_registered(wdt)) {
ret = 0; goto out;
}
/* Run the unregistration in a worker as this can be * run only after ping completion, otherwise the flow will * deadlock on watchdog core mutex.
*/ if (wdt->state == MEI_WDT_RUNNING) { if (res.wdstate & MEI_WDT_WDSTATE_NOT_REQUIRED) {
wdt->state = MEI_WDT_NOT_REQUIRED;
schedule_work(&wdt->unregister);
} goto out;
}
if (wdt->state == MEI_WDT_PROBE) { if (res.wdstate & MEI_WDT_WDSTATE_NOT_REQUIRED) {
wdt->state = MEI_WDT_NOT_REQUIRED;
} else { /* stop the watchdog and register watchdog device */
mei_wdt_stop(wdt);
mei_wdt_register(wdt);
} return;
}
dev_warn(&cldev->dev, "not in correct state %s[%d]\n",
mei_wdt_state_str(wdt->state), wdt->state);
out: if (!completion_done(&wdt->response))
complete(&wdt->response);
}
ret = mei_cldev_enable(cldev); if (ret < 0) {
dev_err(&cldev->dev, "Could not enable cl device\n"); goto err_out;
}
ret = mei_cldev_register_rx_cb(wdt->cldev, mei_wdt_rx); if (ret) {
dev_err(&cldev->dev, "Could not reg rx event ret=%d\n", ret); goto err_disable;
}
ret = mei_cldev_register_notif_cb(wdt->cldev, mei_wdt_notif); /* on legacy devices notification is not supported
*/ if (ret && ret != -EOPNOTSUPP) {
dev_err(&cldev->dev, "Could not reg notif event ret=%d\n", ret); goto err_disable;
}
wd_info.firmware_version = mei_cldev_ver(cldev);
if (wdt->resp_required)
ret = mei_wdt_ping(wdt); else
ret = mei_wdt_register(wdt);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.