mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-05 19:47:48 +00:00
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:
parent
a632ac3dae
commit
f462601b0a
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user