dm: mei: add reset handlers

There are multiple types of resets that need to be handled
by the mei device.
The reset may be initiated from both sides host or fw.
The host requests reset on probe and remove,
power state transaction, and errors,
while ME FW may request reset upon error.
If the native device undergo reset the host application
has to be notified.

Tracked-On: #1536
Signed-off-by: Aviad Nissel <aviad.nissel@intel.com>
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Acked-by: Wang, Yu1 <yu1.wang@intel.com>
This commit is contained in:
Signed-off-by: Aviad Nissel 2018-10-16 01:37:49 +03:00 committed by wenlingz
parent a632ac3dae
commit f462601b0a

View File

@ -222,6 +222,9 @@ static void vmei_dbg_print_hex(const char *title,
#define VMEI_BUF_SZ (VMEI_BUF_DEPTH * VMEI_SLOT_SZ)
#define VMEI_RING_SZ 64
#define MEI_SYSFS_ROOT "/sys/class/mei"
#define MEI_DEV_STATE_LEN 12
struct mei_virtio_cfg {
uint32_t buf_depth;
uint8_t hw_ready;
@ -661,3 +664,85 @@ static int mei_sysfs_read_property_uuid(char *fname, guid_t *uuid)
return guid_parse(buf, sizeof(buf), uuid);
}
static void
vmei_virtual_fw_reset(struct virtio_mei *vmei)
{
DPRINTF("Firmware reset\n");
struct vmei_me_client *e;
vmei_set_status(vmei, VMEI_STS_RESET);
vmei->config->hw_ready = 0;
close(vmei->hbm_fd);
/* disconnect all */
pthread_mutex_lock(&vmei->list_mutex);
LIST_FOREACH(e, &vmei->active_clients, list) {
vmei_me_client_destroy_host_clients(e);
}
pthread_mutex_unlock(&vmei->list_mutex);
}
static void
vmei_reset(void *vth)
{
struct virtio_mei *vmei = vth;
DPRINTF("device reset requested!\n");
vmei_virtual_fw_reset(vmei);
virtio_reset_dev(&vmei->base);
}
static void vmei_del_reset_event(struct virtio_mei *vmei)
{
if (vmei->reset_mevp)
mevent_delete_close(vmei->reset_mevp);
vmei->reset_mevp = NULL;
}
static void
vmei_reset_callback(int fd, enum ev_type type, void *param)
{
static bool first_time = true;
struct virtio_mei *vmei = param;
char buf[MEI_DEV_STATE_LEN] = {0};
int sz;
lseek(fd, 0, SEEK_SET);
sz = read(fd, buf, 12);
if (first_time) {
first_time = false;
return;
}
if (sz != 7 || memcmp(buf, "ENABLED", 7))
return;
DPRINTF("Reset state callback\n");
vmei_virtual_fw_reset(vmei);
vmei_free_me_clients(vmei);
vmei_start(vmei, true);
}
static int vmei_add_reset_event(struct virtio_mei *vmei)
{
char devpath[256];
int dev_state_fd;
snprintf(devpath, sizeof(devpath) - 1, "%s/%s/%s",
MEI_SYSFS_ROOT, vmei->name, "dev_state");
dev_state_fd = open(devpath, O_RDONLY);
if (dev_state_fd < 0)
return -errno;
vmei->reset_mevp = mevent_add(dev_state_fd, EVF_READ_ET,
vmei_reset_callback, vmei);
if (!vmei->reset_mevp) {
close(dev_state_fd);
return -ENOMEM;
}
return 0;
}