/** * struct wdat_instruction - Single ACPI WDAT instruction * @entry: Copy of the ACPI table instruction * @reg: Register the instruction is accessing * @node: Next instruction in action sequence
*/ struct wdat_instruction { struct acpi_wdat_entry entry; void __iomem *reg; struct list_head node;
};
/** * struct wdat_wdt - ACPI WDAT watchdog device * @pdev: Parent platform device * @wdd: Watchdog core device * @period: How long is one watchdog period in ms * @stopped_in_sleep: Is this watchdog stopped by the firmware in S1-S5 * @stopped: Was the watchdog stopped by the driver in suspend * @instructions: An array of instruction lists indexed by an action number from * the WDAT table. There can be %NULL entries for not implemented * actions.
*/ struct wdat_wdt { struct platform_device *pdev; struct watchdog_device wdd; unsignedint period; bool stopped_in_sleep; bool stopped; struct list_head *instructions[MAX_WDAT_ACTIONS];
};
switch (flags) { case ACPI_WDAT_READ_VALUE:
ret = wdat_wdt_read(wdat, instr, &x); if (ret) return ret;
x >>= gas->bit_offset;
x &= mask; if (retval)
*retval = x == value; break;
case ACPI_WDAT_READ_COUNTDOWN:
ret = wdat_wdt_read(wdat, instr, &x); if (ret) return ret;
x >>= gas->bit_offset;
x &= mask; if (retval)
*retval = x; break;
case ACPI_WDAT_WRITE_VALUE:
x = value & mask;
x <<= gas->bit_offset; if (preserve) {
ret = wdat_wdt_read(wdat, instr, &y); if (ret) return ret;
y = y & ~(mask << gas->bit_offset);
x |= y;
}
ret = wdat_wdt_write(wdat, instr, x); if (ret) return ret; break;
case ACPI_WDAT_WRITE_COUNTDOWN:
x = param;
x &= mask;
x <<= gas->bit_offset; if (preserve) {
ret = wdat_wdt_read(wdat, instr, &y); if (ret) return ret;
y = y & ~(mask << gas->bit_offset);
x |= y;
}
ret = wdat_wdt_write(wdat, instr, x); if (ret) return ret; break;
staticint wdat_wdt_enable_reboot(struct wdat_wdt *wdat)
{ int ret;
/* * WDAT specification says that the watchdog is required to reboot * the system when it fires. However, it also states that it is * recommended to make it configurable through hardware register. We * enable reboot now if it is configurable, just in case.
*/
ret = wdat_wdt_run_action(wdat, ACPI_WDAT_SET_REBOOT, 0, NULL); if (ret && ret != -EOPNOTSUPP) {
dev_err(&wdat->pdev->dev, "Failed to enable reboot when watchdog triggers\n"); return ret;
}
ret = wdat_wdt_run_action(wdat, ACPI_WDAT_GET_STATUS, 0, &boot_status); if (ret && ret != -EOPNOTSUPP) {
dev_err(&wdat->pdev->dev, "Failed to read boot status\n"); return;
}
if (boot_status)
wdat->wdd.bootstatus = WDIOF_CARDRESET;
/* Clear the boot status in case BIOS did not do it */
ret = wdat_wdt_run_action(wdat, ACPI_WDAT_SET_STATUS, 0, NULL); if (ret && ret != -EOPNOTSUPP)
dev_err(&wdat->pdev->dev, "Failed to clear boot status\n");
}
ret = wdat_wdt_run_action(wdat, ACPI_WDAT_GET_RUNNING_STATE, 0,
&running); if (ret && ret != -EOPNOTSUPP)
dev_err(&wdat->pdev->dev, "Failed to read running state\n");
if (running)
set_bit(WDOG_HW_RUNNING, &wdat->wdd.status);
}
ret = wdat_wdt_enable_reboot(wdat); if (ret) return ret;
platform_set_drvdata(pdev, wdat);
/* * Set initial timeout so that userspace has time to configure the * watchdog properly after it has opened the device. In some cases * the BIOS default is too short and causes immediate reboot.
*/ if (watchdog_timeout_invalid(&wdat->wdd, timeout)) {
dev_warn(dev, "Invalid timeout %d given, using %d\n",
timeout, WDAT_DEFAULT_TIMEOUT);
timeout = WDAT_DEFAULT_TIMEOUT;
}
ret = wdat_wdt_set_timeout(&wdat->wdd, timeout); if (ret) return ret;
/* * We need to stop the watchdog if firmware is not doing it or if we * are going suspend to idle (where firmware is not involved). If * firmware is stopping the watchdog we kick it here one more time * to give it some time.
*/
wdat->stopped = false; if (acpi_target_system_state() == ACPI_STATE_S0 ||
!wdat->stopped_in_sleep) {
ret = wdat_wdt_stop(&wdat->wdd); if (!ret)
wdat->stopped = true;
} else {
ret = wdat_wdt_ping(&wdat->wdd);
}
if (!wdat->stopped) { /* * Looks like the boot firmware reinitializes the watchdog * before it hands off to the OS on resume from sleep so we * stop and reprogram the watchdog here.
*/
ret = wdat_wdt_stop(&wdat->wdd); if (ret) return ret;
ret = wdat_wdt_set_timeout(&wdat->wdd, wdat->wdd.timeout); if (ret) return ret;
ret = wdat_wdt_enable_reboot(wdat); if (ret) return ret;
ret = wdat_wdt_ping(&wdat->wdd); if (ret) return ret;
}
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.