summaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/mei/init.c')
-rw-r--r--drivers/misc/mei/init.c86
1 files changed, 59 insertions, 27 deletions
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 6ec530168af..713d89fedc4 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -14,6 +14,7 @@
*
*/
+#include <linux/export.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <linux/wait.h>
@@ -22,6 +23,7 @@
#include <linux/mei.h>
#include "mei_dev.h"
+#include "hbm.h"
#include "client.h"
const char *mei_dev_state_str(int state)
@@ -31,9 +33,8 @@ const char *mei_dev_state_str(int state)
MEI_DEV_STATE(INITIALIZING);
MEI_DEV_STATE(INIT_CLIENTS);
MEI_DEV_STATE(ENABLED);
- MEI_DEV_STATE(RESETING);
+ MEI_DEV_STATE(RESETTING);
MEI_DEV_STATE(DISABLED);
- MEI_DEV_STATE(RECOVERING_FROM_RESET);
MEI_DEV_STATE(POWER_DOWN);
MEI_DEV_STATE(POWER_UP);
default:
@@ -46,7 +47,9 @@ 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;
@@ -56,19 +59,27 @@ void mei_device_init(struct mei_device *dev)
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);
+
}
+EXPORT_SYMBOL_GPL(mei_device_init);
/**
- * mei_hw_init - initializes host and fw to start work.
+ * mei_start - initializes host and fw to start work.
*
* @dev: the device structure
*
* returns 0 on success, <0 on failure.
*/
-int mei_hw_init(struct mei_device *dev)
+int mei_start(struct mei_device *dev)
{
- int ret = 0;
-
mutex_lock(&dev->device_lock);
/* acknowledge interrupt and stop interupts */
@@ -76,29 +87,15 @@ int mei_hw_init(struct mei_device *dev)
mei_hw_config(dev);
- dev->recvd_msg = false;
dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n");
mei_reset(dev, 1);
- /* wait for ME to turn on ME_RDY */
- if (!dev->recvd_msg) {
- mutex_unlock(&dev->device_lock);
- ret = wait_event_interruptible_timeout(dev->wait_recvd_msg,
- dev->recvd_msg,
- mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT));
- mutex_lock(&dev->device_lock);
- }
-
- if (ret <= 0 && !dev->recvd_msg) {
- dev->dev_state = MEI_DEV_DISABLED;
- dev_dbg(&dev->pdev->dev,
- "wait_event_interruptible_timeout failed"
- "on wait for ME to turn on ME_RDY.\n");
+ if (mei_hbm_start_wait(dev)) {
+ dev_err(&dev->pdev->dev, "HBM haven't started");
goto err;
}
-
if (!mei_host_is_ready(dev)) {
dev_err(&dev->pdev->dev, "host is not ready.\n");
goto err;
@@ -115,7 +112,6 @@ int mei_hw_init(struct mei_device *dev)
goto err;
}
- dev->recvd_msg = false;
dev_dbg(&dev->pdev->dev, "link layer has been established.\n");
mutex_unlock(&dev->device_lock);
@@ -126,6 +122,7 @@ err:
mutex_unlock(&dev->device_lock);
return -ENODEV;
}
+EXPORT_SYMBOL_GPL(mei_start);
/**
* mei_reset - resets host and fw.
@@ -137,9 +134,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
{
bool unexpected;
- if (dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET)
- return;
-
unexpected = (dev->dev_state != MEI_DEV_INITIALIZING &&
dev->dev_state != MEI_DEV_DISABLED &&
dev->dev_state != MEI_DEV_POWER_DOWN &&
@@ -147,11 +141,12 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
mei_hw_reset(dev, interrupts_enabled);
+ dev->hbm_state = MEI_HBM_IDLE;
if (dev->dev_state != MEI_DEV_INITIALIZING) {
if (dev->dev_state != MEI_DEV_DISABLED &&
dev->dev_state != MEI_DEV_POWER_DOWN)
- dev->dev_state = MEI_DEV_RESETING;
+ dev->dev_state = MEI_DEV_RESETTING;
mei_cl_all_disconnect(dev);
@@ -176,13 +171,50 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n",
mei_dev_state_str(dev->dev_state));
+ if (!interrupts_enabled) {
+ dev_dbg(&dev->pdev->dev, "intr not enabled end of reset\n");
+ return;
+ }
+
+ mei_hw_start(dev);
+
+ dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
+ /* link is established * start sending messages. */
+
+ dev->dev_state = MEI_DEV_INIT_CLIENTS;
+
+ mei_hbm_start_req(dev);
+
/* wake up all readings so they can be interrupted */
mei_cl_all_read_wakeup(dev);
/* remove all waiting requests */
mei_cl_all_write_clear(dev);
}
+EXPORT_SYMBOL_GPL(mei_reset);
+
+void mei_stop(struct mei_device *dev)
+{
+ dev_dbg(&dev->pdev->dev, "stopping the device.\n");
+
+ mutex_lock(&dev->device_lock);
+
+ cancel_delayed_work(&dev->timer_work);
+ mei_wd_stop(dev);
+
+ mei_nfc_host_exit();
+
+ dev->dev_state = MEI_DEV_POWER_DOWN;
+ mei_reset(dev, 0);
+
+ mutex_unlock(&dev->device_lock);
+
+ flush_scheduled_work();
+
+ mei_watchdog_unregister(dev);
+}
+EXPORT_SYMBOL_GPL(mei_stop);