/** * mei_fw_status2str - convert fw status registers to printable string * * @fw_status: firmware status * @buf: string buffer at minimal size MEI_FW_STATUS_STR_SZ * @len: buffer len must be >= MEI_FW_STATUS_STR_SZ * * Return: number of bytes written or -EINVAL if buffer is to small
*/
ssize_t mei_fw_status2str(struct mei_fw_status *fw_status, char *buf, size_t len)
{
ssize_t cnt = 0; int i;
buf[0] = '\0';
if (len < MEI_FW_STATUS_STR_SZ) return -EINVAL;
for (i = 0; i < fw_status->count; i++)
cnt += scnprintf(buf + cnt, len - cnt, "%08X ",
fw_status->status[i]);
/* drop last space */
buf[cnt] = '\0'; return cnt;
}
EXPORT_SYMBOL_GPL(mei_fw_status2str);
/** * mei_cancel_work - Cancel mei background jobs * * @dev: the device structure
*/ void mei_cancel_work(struct mei_device *dev)
{
cancel_work_sync(&dev->reset_work);
cancel_work_sync(&dev->bus_rescan_work);
/** * mei_reset - resets host and fw. * * @dev: the device structure * * Return: 0 on success or < 0 if the reset hasn't succeeded
*/ int mei_reset(struct mei_device *dev)
{ enum mei_dev_state state = dev->dev_state; bool interrupts_enabled; int ret;
if (state != MEI_DEV_INITIALIZING &&
state != MEI_DEV_DISABLED &&
state != MEI_DEV_POWER_DOWN &&
state != MEI_DEV_POWER_UP) { char fw_sts_str[MEI_FW_STATUS_STR_SZ];
/* we're already in reset, cancel the init timer * if the reset was called due the hbm protocol error * we need to call it before hw start * so the hbm watchdog won't kick in
*/
mei_hbm_idle(dev);
/* enter reset flow */
interrupts_enabled = state != MEI_DEV_POWER_DOWN;
mei_set_devstate(dev, MEI_DEV_RESETTING);
dev->reset_count++; if (dev->reset_count > MEI_MAX_CONSEC_RESET) {
dev_err(dev->dev, "reset: reached maximal consecutive resets: disabling the device\n");
mei_set_devstate(dev, MEI_DEV_DISABLED); return -ENODEV;
}
ret = mei_hw_reset(dev, interrupts_enabled); /* fall through and remove the sw state even if hw reset has failed */
/* no need to clean up software state in case of power up */ if (state != MEI_DEV_INITIALIZING && state != MEI_DEV_POWER_UP)
mei_cl_all_disconnect(dev);
mei_hbm_reset(dev);
/* clean stale FW version */
dev->fw_ver_received = 0;
if (ret) {
dev_err(dev->dev, "hw_reset failed ret = %d\n", ret); return ret;
}
if (state == MEI_DEV_POWER_DOWN) {
dev_dbg(dev->dev, "powering down: end of reset\n");
mei_set_devstate(dev, MEI_DEV_DISABLED); return 0;
}
ret = mei_hw_start(dev); if (ret) { char fw_sts_str[MEI_FW_STATUS_STR_SZ];
mei_fw_status_str(dev, fw_sts_str, MEI_FW_STATUS_STR_SZ);
dev_err(dev->dev, "hw_start failed ret = %d fw status = %s\n", ret, fw_sts_str); return ret;
}
if (dev->dev_state != MEI_DEV_RESETTING) {
dev_dbg(dev->dev, "wrong state = %d on link start\n", dev->dev_state); return 0;
}
dev_dbg(dev->dev, "link is established start sending messages.\n");
mei_set_devstate(dev, MEI_DEV_INIT_CLIENTS);
ret = mei_hbm_start_req(dev); if (ret) {
dev_err(dev->dev, "hbm_start failed ret = %d\n", ret);
mei_set_devstate(dev, MEI_DEV_RESETTING); return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(mei_reset);
/** * mei_start - initializes host and fw to start work. * * @dev: the device structure * * Return: 0 on success, <0 on failure.
*/ int mei_start(struct mei_device *dev)
{ int ret;
mutex_lock(&dev->device_lock);
/* acknowledge interrupt and stop interrupts */
mei_clear_interrupts(dev);
ret = mei_hw_config(dev); if (ret) goto err;
dev_dbg(dev->dev, "reset in start the mei device.\n");
dev->reset_count = 0; do {
mei_set_devstate(dev, MEI_DEV_INITIALIZING);
ret = mei_reset(dev);
if (ret == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) {
dev_err(dev->dev, "reset failed ret = %d", ret); goto err;
}
} while (ret);
if (mei_hbm_start_wait(dev)) {
dev_err(dev->dev, "HBM haven't started"); goto err;
}
if (!mei_hbm_version_is_supported(dev)) {
dev_dbg(dev->dev, "MEI start failed.\n"); goto err;
}
dev_dbg(dev->dev, "link layer has been established.\n");
/** * mei_restart - restart device after suspend * * @dev: the device structure * * Return: 0 on success or -ENODEV if the restart hasn't succeeded
*/ int mei_restart(struct mei_device *dev)
{ int err;
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.