virtio-heci: Add firmware reset handling

Now, we treat a read/write ENODEV error as a firmware reset. When MEI
reset happens in driver, we need disconnect all active clients and
restart HBM flow.

Signed-off-by: Liu Shuo <shuo.a.liu@intel.com>
Reviewed-by: Li Hao <hao.l.li@intel.com>
Reviewed-by: Wang Yu <yu1.wang@intel.com>
Reviewed-by: Zhao, Yakui <yakui.zhao@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Liu Shuo 2018-04-03 10:25:38 +08:00 committed by Jack Ren
parent 37cae5884d
commit 33e84efef9

View File

@ -124,6 +124,7 @@ struct virtio_heci {
struct mei_enumerate_me_clients me_clients_map;
volatile bool deiniting;
volatile bool resetting;
volatile bool pending_reset;
pthread_t tx_thread;
pthread_mutex_t tx_mutex;
@ -409,6 +410,7 @@ virtio_heci_destroy_client(struct virtio_heci *vheci,
static int
native_heci_read(struct virtio_heci_client *client)
{
struct virtio_heci *vheci = client->vheci;
int len;
if (client->client_fd <= 0) {
@ -421,6 +423,8 @@ native_heci_read(struct virtio_heci_client *client)
len = read(client->client_fd, client->recv_buf, client->recv_buf_sz);
if (len < 0) {
WPRINTF(("vheci: read failed! read error[%d]\r\n", errno));
if (errno == ENODEV)
vheci->pending_reset = true;
return len;
}
DPRINTF(("vheci: RX: ME[%d]fd[%d] Append data(len[%d]) "
@ -435,6 +439,7 @@ native_heci_read(struct virtio_heci_client *client)
static int
native_heci_write(struct virtio_heci_client *client)
{
struct virtio_heci *vheci = client->vheci;
int len;
if (client->client_fd <= 0) {
@ -443,8 +448,11 @@ native_heci_write(struct virtio_heci_client *client)
return -1;
}
len = write(client->client_fd, client->send_buf, client->send_idx);
if (len < 0)
if (len < 0) {
WPRINTF(("vheci: write failed! write error[%d]\r\n", errno));
if (errno == ENODEV)
vheci->pending_reset = true;
}
return len;
}
@ -482,6 +490,14 @@ virtio_heci_rx_callback(int fd, enum ev_type type, void *param)
out:
pthread_mutex_unlock(&vheci->rx_mutex);
virtio_heci_client_put(vheci, client);
if (vheci->pending_reset) {
vheci->pending_reset = false;
virtio_heci_virtual_fw_reset(vheci);
/* Let's wait 100ms for HBM enumeration done */
usleep(100000);
virtio_config_changed(&vheci->base);
}
}
static void
@ -490,6 +506,7 @@ virtio_heci_reset(void *vth)
struct virtio_heci *vheci = vth;
DPRINTF(("vheci: device reset requested !\r\n"));
virtio_heci_virtual_fw_reset(vheci);
virtio_reset_dev(&vheci->base);
}
@ -874,6 +891,13 @@ out:
send_failed:
virtio_heci_client_put(vheci, client);
failed:
if (vheci->pending_reset) {
vheci->pending_reset = false;
virtio_heci_virtual_fw_reset(vheci);
/* Let's wait 100ms for HBM enumeration done */
usleep(100000);
virtio_config_changed(&vheci->base);
}
/* drop the data */
vq_relchain(vq, idx, tlen);
}