summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/mei/hbm.c200
-rw-r--r--drivers/misc/mei/hbm.h6
-rw-r--r--drivers/misc/mei/hw-me.c32
-rw-r--r--drivers/misc/mei/init.c100
-rw-r--r--drivers/misc/mei/interrupt.c9
-rw-r--r--drivers/misc/mei/mei_dev.h1
6 files changed, 210 insertions, 138 deletions
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 9b3a0fb7f265..8109b9a98cc3 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -28,9 +28,9 @@
*
* @dev: the device structure
*
- * returns none.
+ * returns 0 on success -ENOMEM on allocation failure
*/
-static void mei_hbm_me_cl_allocate(struct mei_device *dev)
+static int mei_hbm_me_cl_allocate(struct mei_device *dev)
{
struct mei_me_client *clients;
int b;
@@ -44,7 +44,7 @@ static void mei_hbm_me_cl_allocate(struct mei_device *dev)
dev->me_clients_num++;
if (dev->me_clients_num == 0)
- return;
+ return 0;
kfree(dev->me_clients);
dev->me_clients = NULL;
@@ -56,12 +56,10 @@ static void mei_hbm_me_cl_allocate(struct mei_device *dev)
sizeof(struct mei_me_client), GFP_KERNEL);
if (!clients) {
dev_err(&dev->pdev->dev, "memory allocation for ME clients failed.\n");
- dev->dev_state = MEI_DEV_RESETTING;
- mei_reset(dev, 1);
- return;
+ return -ENOMEM;
}
dev->me_clients = clients;
- return;
+ return 0;
}
/**
@@ -137,7 +135,7 @@ int mei_hbm_start_wait(struct mei_device *dev)
mutex_unlock(&dev->device_lock);
ret = wait_event_interruptible_timeout(dev->wait_recvd_msg,
dev->hbm_state == MEI_HBM_IDLE ||
- dev->hbm_state > MEI_HBM_START,
+ dev->hbm_state >= MEI_HBM_STARTED,
mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT));
mutex_lock(&dev->device_lock);
@@ -153,12 +151,15 @@ int mei_hbm_start_wait(struct mei_device *dev)
* mei_hbm_start_req - sends start request message.
*
* @dev: the device structure
+ *
+ * returns 0 on success and < 0 on failure
*/
int mei_hbm_start_req(struct mei_device *dev)
{
struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
struct hbm_host_version_request *start_req;
const size_t len = sizeof(struct hbm_host_version_request);
+ int ret;
mei_hbm_hdr(mei_hdr, len);
@@ -170,12 +171,13 @@ int mei_hbm_start_req(struct mei_device *dev)
start_req->host_version.minor_version = HBM_MINOR_VERSION;
dev->hbm_state = MEI_HBM_IDLE;
- if (mei_write_message(dev, mei_hdr, dev->wr_msg.data)) {
- dev_err(&dev->pdev->dev, "version message write failed\n");
- dev->dev_state = MEI_DEV_RESETTING;
- mei_reset(dev, 1);
- return -EIO;
+ ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
+ if (ret) {
+ dev_err(&dev->pdev->dev, "version message write failed: ret = %d\n",
+ ret);
+ return ret;
}
+
dev->hbm_state = MEI_HBM_START;
dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
return 0;
@@ -186,13 +188,15 @@ int mei_hbm_start_req(struct mei_device *dev)
*
* @dev: the device structure
*
- * returns none.
+ * returns 0 on success and < 0 on failure
*/
-static void mei_hbm_enum_clients_req(struct mei_device *dev)
+static int mei_hbm_enum_clients_req(struct mei_device *dev)
{
struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
struct hbm_host_enum_request *enum_req;
const size_t len = sizeof(struct hbm_host_enum_request);
+ int ret;
+
/* enumerate clients */
mei_hbm_hdr(mei_hdr, len);
@@ -200,14 +204,15 @@ static void mei_hbm_enum_clients_req(struct mei_device *dev)
memset(enum_req, 0, len);
enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
- if (mei_write_message(dev, mei_hdr, dev->wr_msg.data)) {
- dev->dev_state = MEI_DEV_RESETTING;
- dev_err(&dev->pdev->dev, "enumeration request write failed.\n");
- mei_reset(dev, 1);
+ ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
+ if (ret) {
+ dev_err(&dev->pdev->dev, "enumeration request write failed: ret = %d.\n",
+ ret);
+ return ret;
}
dev->hbm_state = MEI_HBM_ENUM_CLIENTS;
dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
- return;
+ return 0;
}
/**
@@ -215,7 +220,7 @@ static void mei_hbm_enum_clients_req(struct mei_device *dev)
*
* @dev: the device structure
*
- * returns none.
+ * returns 0 on success and < 0 on failure
*/
static int mei_hbm_prop_req(struct mei_device *dev)
@@ -226,7 +231,7 @@ static int mei_hbm_prop_req(struct mei_device *dev)
const size_t len = sizeof(struct hbm_props_request);
unsigned long next_client_index;
unsigned long client_num;
-
+ int ret;
client_num = dev->me_client_presentation_num;
@@ -253,12 +258,11 @@ static int mei_hbm_prop_req(struct mei_device *dev)
prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
prop_req->address = next_client_index;
- if (mei_write_message(dev, mei_hdr, dev->wr_msg.data)) {
- dev->dev_state = MEI_DEV_RESETTING;
- dev_err(&dev->pdev->dev, "properties request write failed\n");
- mei_reset(dev, 1);
-
- return -EIO;
+ ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
+ if (ret) {
+ dev_err(&dev->pdev->dev, "properties request write failed: ret = %d\n",
+ ret);
+ return ret;
}
dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
@@ -559,8 +563,10 @@ bool mei_hbm_version_is_supported(struct mei_device *dev)
*
* @dev: the device structure
* @mei_hdr: header of bus message
+ *
+ * returns 0 on success and < 0 on failure
*/
-void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
+int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
{
struct mei_bus_message *mei_msg;
struct mei_me_client *me_client;
@@ -579,6 +585,10 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
switch (mei_msg->hbm_cmd) {
case HOST_START_RES_CMD:
+ dev_dbg(&dev->pdev->dev, "hbm: start: response message received.\n");
+
+ dev->init_clients_timer = 0;
+
version_res = (struct hbm_host_version_response *)mei_msg;
dev_dbg(&dev->pdev->dev, "HBM VERSION: DRIVER=%02d:%02d DEVICE=%02d:%02d\n",
@@ -597,73 +607,89 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
}
if (!mei_hbm_version_is_supported(dev)) {
- dev_warn(&dev->pdev->dev, "hbm version mismatch: stopping the driver.\n");
+ dev_warn(&dev->pdev->dev, "hbm: start: version mismatch - stopping the driver.\n");
- dev->hbm_state = MEI_HBM_STOP;
+ dev->hbm_state = MEI_HBM_STOPPED;
mei_hbm_stop_req_prepare(dev, &dev->wr_msg.hdr,
dev->wr_msg.data);
- mei_write_message(dev, &dev->wr_msg.hdr,
- dev->wr_msg.data);
+ if (mei_write_message(dev, &dev->wr_msg.hdr,
+ dev->wr_msg.data)) {
+ dev_err(&dev->pdev->dev, "hbm: start: failed to send stop request\n");
+ return -EIO;
+ }
+ break;
+ }
- return;
+ if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
+ dev->hbm_state != MEI_HBM_START) {
+ dev_err(&dev->pdev->dev, "hbm: start: state mismatch, [%d, %d]\n",
+ dev->dev_state, dev->hbm_state);
+ return -EPROTO;
}
- if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
- dev->hbm_state == MEI_HBM_START) {
- dev->init_clients_timer = 0;
- mei_hbm_enum_clients_req(dev);
- } else {
- dev_err(&dev->pdev->dev, "reset: wrong host start response\n");
- mei_reset(dev, 1);
- return;
+ dev->hbm_state = MEI_HBM_STARTED;
+
+ if (mei_hbm_enum_clients_req(dev)) {
+ dev_err(&dev->pdev->dev, "hbm: start: failed to send enumeration request\n");
+ return -EIO;
}
wake_up_interruptible(&dev->wait_recvd_msg);
- dev_dbg(&dev->pdev->dev, "host start response message received.\n");
break;
case CLIENT_CONNECT_RES_CMD:
+ dev_dbg(&dev->pdev->dev, "hbm: client connect response: message received.\n");
+
connect_res = (struct hbm_client_connect_response *) mei_msg;
mei_hbm_cl_connect_res(dev, connect_res);
- dev_dbg(&dev->pdev->dev, "client connect response message received.\n");
wake_up(&dev->wait_recvd_msg);
break;
case CLIENT_DISCONNECT_RES_CMD:
+ dev_dbg(&dev->pdev->dev, "hbm: client disconnect response: message received.\n");
+
disconnect_res = (struct hbm_client_connect_response *) mei_msg;
mei_hbm_cl_disconnect_res(dev, disconnect_res);
- dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n");
wake_up(&dev->wait_recvd_msg);
break;
case MEI_FLOW_CONTROL_CMD:
+ dev_dbg(&dev->pdev->dev, "hbm: client flow control response: message received.\n");
+
flow_control = (struct hbm_flow_control *) mei_msg;
mei_hbm_cl_flow_control_res(dev, flow_control);
- dev_dbg(&dev->pdev->dev, "client flow control response message received.\n");
break;
case HOST_CLIENT_PROPERTIES_RES_CMD:
+ dev_dbg(&dev->pdev->dev, "hbm: properties response: message received.\n");
+
+ dev->init_clients_timer = 0;
+
+ if (dev->me_clients == NULL) {
+ dev_err(&dev->pdev->dev, "hbm: properties response: mei_clients not allocated\n");
+ return -EPROTO;
+ }
+
props_res = (struct hbm_props_response *)mei_msg;
me_client = &dev->me_clients[dev->me_client_presentation_num];
- if (props_res->status || !dev->me_clients) {
- dev_err(&dev->pdev->dev, "reset: properties response hbm wrong status.\n");
- mei_reset(dev, 1);
- return;
+ if (props_res->status) {
+ dev_err(&dev->pdev->dev, "hbm: properties response: wrong status = %d\n",
+ props_res->status);
+ return -EPROTO;
}
if (me_client->client_id != props_res->address) {
- dev_err(&dev->pdev->dev, "reset: host properties response address mismatch\n");
- mei_reset(dev, 1);
- return;
+ dev_err(&dev->pdev->dev, "hbm: properties response: address mismatch %d ?= %d\n",
+ me_client->client_id, props_res->address);
+ return -EPROTO;
}
if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) {
- dev_err(&dev->pdev->dev, "reset: unexpected properties response\n");
- mei_reset(dev, 1);
-
- return;
+ dev_err(&dev->pdev->dev, "hbm: properties response: state mismatch, [%d, %d]\n",
+ dev->dev_state, dev->hbm_state);
+ return -EPROTO;
}
me_client->props = props_res->client_properties;
@@ -671,49 +697,70 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
dev->me_client_presentation_num++;
/* request property for the next client */
- mei_hbm_prop_req(dev);
+ if (mei_hbm_prop_req(dev))
+ return -EIO;
break;
case HOST_ENUM_RES_CMD:
+ dev_dbg(&dev->pdev->dev, "hbm: enumeration response: message received\n");
+
+ dev->init_clients_timer = 0;
+
enum_res = (struct hbm_host_enum_response *) mei_msg;
BUILD_BUG_ON(sizeof(dev->me_clients_map)
< sizeof(enum_res->valid_addresses));
memcpy(dev->me_clients_map, enum_res->valid_addresses,
sizeof(enum_res->valid_addresses));
- if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
- dev->hbm_state == MEI_HBM_ENUM_CLIENTS) {
- dev->init_clients_timer = 0;
- mei_hbm_me_cl_allocate(dev);
- dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
-
- /* first property reqeust */
- mei_hbm_prop_req(dev);
- } else {
- dev_err(&dev->pdev->dev, "reset: unexpected enumeration response hbm.\n");
- mei_reset(dev, 1);
- return;
+
+ if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
+ dev->hbm_state != MEI_HBM_ENUM_CLIENTS) {
+ dev_err(&dev->pdev->dev, "hbm: enumeration response: state mismatch, [%d, %d]\n",
+ dev->dev_state, dev->hbm_state);
+ return -EPROTO;
}
+
+ if (mei_hbm_me_cl_allocate(dev)) {
+ dev_err(&dev->pdev->dev, "hbm: enumeration response: cannot allocate clients array\n");
+ return -ENOMEM;
+ }
+
+ dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
+
+ /* first property request */
+ if (mei_hbm_prop_req(dev))
+ return -EIO;
+
break;
case HOST_STOP_RES_CMD:
+ dev_dbg(&dev->pdev->dev, "hbm: stop response: message received\n");
+
+ dev->init_clients_timer = 0;
+
+ if (dev->hbm_state != MEI_HBM_STOPPED) {
+ dev_err(&dev->pdev->dev, "hbm: stop response: state mismatch, [%d, %d]\n",
+ dev->dev_state, dev->hbm_state);
+ return -EPROTO;
+ }
- if (dev->hbm_state != MEI_HBM_STOP)
- dev_err(&dev->pdev->dev, "unexpected stop response hbm.\n");
dev->dev_state = MEI_DEV_DISABLED;
- dev_info(&dev->pdev->dev, "reset: FW stop response.\n");
- mei_reset(dev, 1);
+ dev_info(&dev->pdev->dev, "hbm: stop response: resetting.\n");
+ /* force the reset */
+ return -EPROTO;
break;
case CLIENT_DISCONNECT_REQ_CMD:
- /* search for client */
+ dev_dbg(&dev->pdev->dev, "hbm: disconnect request: message received\n");
+
disconnect_req = (struct hbm_client_connect_request *)mei_msg;
mei_hbm_fw_disconnect_req(dev, disconnect_req);
break;
case ME_STOP_REQ_CMD:
+ dev_dbg(&dev->pdev->dev, "hbm: stop request: message received\n");
- dev->hbm_state = MEI_HBM_STOP;
+ dev->hbm_state = MEI_HBM_STOPPED;
mei_hbm_stop_req_prepare(dev, &dev->wr_ext_msg.hdr,
dev->wr_ext_msg.data);
break;
@@ -722,5 +769,6 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
break;
}
+ return 0;
}
diff --git a/drivers/misc/mei/hbm.h b/drivers/misc/mei/hbm.h
index 4ae2e56e404f..f2540fff7080 100644
--- a/drivers/misc/mei/hbm.h
+++ b/drivers/misc/mei/hbm.h
@@ -32,13 +32,13 @@ struct mei_cl;
enum mei_hbm_state {
MEI_HBM_IDLE = 0,
MEI_HBM_START,
+ MEI_HBM_STARTED,
MEI_HBM_ENUM_CLIENTS,
MEI_HBM_CLIENT_PROPERTIES,
- MEI_HBM_STARTED,
- MEI_HBM_STOP,
+ MEI_HBM_STOPPED,
};
-void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr);
+int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr);
static inline void mei_hbm_hdr(struct mei_msg_hdr *hdr, size_t length)
{
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 3412adcdaeb0..6c07623704c2 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -469,7 +469,7 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
struct mei_device *dev = (struct mei_device *) dev_id;
struct mei_cl_cb complete_list;
s32 slots;
- int rets;
+ int rets = 0;
dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
/* initialize our complete list */
@@ -487,10 +487,9 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
dev->dev_state != MEI_DEV_INITIALIZING &&
dev->dev_state != MEI_DEV_POWER_DOWN &&
dev->dev_state != MEI_DEV_POWER_UP) {
- dev_dbg(&dev->pdev->dev, "FW not ready.\n");
- mei_reset(dev, 1);
- mutex_unlock(&dev->device_lock);
- return IRQ_HANDLED;
+ dev_warn(&dev->pdev->dev, "FW not ready: resetting.\n");
+ schedule_work(&dev->reset_work);
+ goto end;
}
/* check if we need to start the dev */
@@ -500,15 +499,12 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
dev->recvd_hw_ready = true;
wake_up_interruptible(&dev->wait_hw_ready);
-
- mutex_unlock(&dev->device_lock);
- return IRQ_HANDLED;
} else {
+
dev_dbg(&dev->pdev->dev, "Reset Completed.\n");
mei_me_hw_reset_release(dev);
- mutex_unlock(&dev->device_lock);
- return IRQ_HANDLED;
}
+ goto end;
}
/* check slots available for reading */
slots = mei_count_full_read_slots(dev);
@@ -516,21 +512,23 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
/* we have urgent data to send so break the read */
if (dev->wr_ext_msg.hdr.length)
break;
- dev_dbg(&dev->pdev->dev, "slots =%08x\n", slots);
- dev_dbg(&dev->pdev->dev, "call mei_irq_read_handler.\n");
+ dev_dbg(&dev->pdev->dev, "slots to read = %08x\n", slots);
rets = mei_irq_read_handler(dev, &complete_list, &slots);
- if (rets)
+ if (rets) {
+ schedule_work(&dev->reset_work);
goto end;
+ }
}
+
rets = mei_irq_write_handler(dev, &complete_list);
-end:
- dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
- dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
- mutex_unlock(&dev->device_lock);
+ dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
mei_irq_compl_handler(dev, &complete_list);
+end:
+ dev_dbg(&dev->pdev->dev, "interrupt thread end ret = %d\n", rets);
+ mutex_unlock(&dev->device_lock);
return IRQ_HANDLED;
}
static const struct mei_hw_ops mei_me_hw_ops = {
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 83c879bf9967..87c077bae5d8 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -43,42 +43,6 @@ const char *mei_dev_state_str(int state)
#undef MEI_DEV_STATE
}
-void mei_device_init(struct mei_device *dev)
-{
- /* setup our list array */
- INIT_LIST_HEAD(&dev->file_list);
- INIT_LIST_HEAD(&dev->device_list);
- mutex_init(&dev->device_lock);
- init_waitqueue_head(&dev->wait_hw_ready);
- init_waitqueue_head(&dev->wait_recvd_msg);
- init_waitqueue_head(&dev->wait_stop_wd);
- dev->dev_state = MEI_DEV_INITIALIZING;
-
- mei_io_list_init(&dev->read_list);
- mei_io_list_init(&dev->write_list);
- mei_io_list_init(&dev->write_waiting_list);
- mei_io_list_init(&dev->ctrl_wr_list);
- mei_io_list_init(&dev->ctrl_rd_list);
-
- INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
- INIT_WORK(&dev->init_work, mei_host_client_init);
-
- INIT_LIST_HEAD(&dev->wd_cl.link);
- INIT_LIST_HEAD(&dev->iamthif_cl.link);
- mei_io_list_init(&dev->amthif_cmd_list);
- mei_io_list_init(&dev->amthif_rd_complete_list);
-
- bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
- dev->open_handle_count = 0;
-
- /*
- * Reserving the first client ID
- * 0: Reserved for MEI Bus Message communications
- */
- bitmap_set(dev->host_clients_map, 0, 1);
-}
-EXPORT_SYMBOL_GPL(mei_device_init);
-
/**
* mei_start - initializes host and fw to start work.
*
@@ -131,10 +95,15 @@ err:
}
EXPORT_SYMBOL_GPL(mei_start);
-
+/**
+ * mei_cancel_work. Cancel mei background jobs
+ *
+ * @dev: the device structure
+ */
void mei_cancel_work(struct mei_device *dev)
{
cancel_work_sync(&dev->init_work);
+ cancel_work_sync(&dev->reset_work);
cancel_delayed_work(&dev->timer_work);
}
@@ -215,11 +184,27 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
dev->dev_state = MEI_DEV_INIT_CLIENTS;
- mei_hbm_start_req(dev);
-
+ ret = mei_hbm_start_req(dev);
+ if (ret) {
+ dev_err(&dev->pdev->dev, "hbm_start failed disabling the device\n");
+ dev->dev_state = MEI_DEV_DISABLED;
+ return;
+ }
}
EXPORT_SYMBOL_GPL(mei_reset);
+static void mei_reset_work(struct work_struct *work)
+{
+ struct mei_device *dev =
+ container_of(work, struct mei_device, reset_work);
+
+ mutex_lock(&dev->device_lock);
+
+ mei_reset(dev, true);
+
+ mutex_unlock(&dev->device_lock);
+}
+
void mei_stop(struct mei_device *dev)
{
dev_dbg(&dev->pdev->dev, "stopping the device.\n");
@@ -243,3 +228,40 @@ EXPORT_SYMBOL_GPL(mei_stop);
+void mei_device_init(struct mei_device *dev)
+{
+ /* setup our list array */
+ INIT_LIST_HEAD(&dev->file_list);
+ INIT_LIST_HEAD(&dev->device_list);
+ mutex_init(&dev->device_lock);
+ init_waitqueue_head(&dev->wait_hw_ready);
+ init_waitqueue_head(&dev->wait_recvd_msg);
+ init_waitqueue_head(&dev->wait_stop_wd);
+ dev->dev_state = MEI_DEV_INITIALIZING;
+
+ mei_io_list_init(&dev->read_list);
+ mei_io_list_init(&dev->write_list);
+ mei_io_list_init(&dev->write_waiting_list);
+ mei_io_list_init(&dev->ctrl_wr_list);
+ mei_io_list_init(&dev->ctrl_rd_list);
+
+ INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
+ INIT_WORK(&dev->init_work, mei_host_client_init);
+ INIT_WORK(&dev->reset_work, mei_reset_work);
+
+ INIT_LIST_HEAD(&dev->wd_cl.link);
+ INIT_LIST_HEAD(&dev->iamthif_cl.link);
+ mei_io_list_init(&dev->amthif_cmd_list);
+ mei_io_list_init(&dev->amthif_rd_complete_list);
+
+ bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
+ dev->open_handle_count = 0;
+
+ /*
+ * Reserving the first client ID
+ * 0: Reserved for MEI Bus Message communications
+ */
+ bitmap_set(dev->host_clients_map, 0, 1);
+}
+EXPORT_SYMBOL_GPL(mei_device_init);
+
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 9c8225b945c3..bbb61bec863b 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -329,9 +329,12 @@ int mei_irq_read_handler(struct mei_device *dev,
/* HBM message */
if (mei_hdr->host_addr == 0 && mei_hdr->me_addr == 0) {
- mei_hbm_dispatch(dev, mei_hdr);
- ret = 0;
- dev_dbg(&dev->pdev->dev, "mei_hbm_dispatch.\n");
+ ret = mei_hbm_dispatch(dev, mei_hdr);
+ if (ret) {
+ dev_dbg(&dev->pdev->dev, "mei_hbm_dispatch failed ret = %d\n",
+ ret);
+ goto end;
+ }
goto reset_slots;
}
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index d92ca0c93f7f..3f242e15f8f1 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -428,6 +428,7 @@ struct mei_device {
bool iamthif_canceled;
struct work_struct init_work;
+ struct work_struct reset_work;
/* List of bus devices */
struct list_head device_list;