]> Pileus Git - ~andy/linux/commitdiff
mei: add hw start callback
authorTomas Winkler <tomas.winkler@intel.com>
Mon, 11 Mar 2013 16:27:03 +0000 (18:27 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 15 Mar 2013 18:10:49 +0000 (11:10 -0700)
This callback wraps up hardware dependent details
of the hardware initialization.

This callback also contains host ready setting
so we can remove host_set_ready callback

In ME we switch to waiting on event so
we can streamline the initialization flow.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/mei/hw-me.c
drivers/misc/mei/init.c
drivers/misc/mei/mei_dev.h

index d21e5a761f2cd0632728582ef7f450ac54cb1214..df9b43d81eeadd2f1b2c016dd13b1d8640d80fcb 100644 (file)
@@ -222,6 +222,38 @@ static bool mei_me_hw_is_ready(struct mei_device *dev)
        return (hw->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA;
 }
 
+static int mei_me_hw_ready_wait(struct mei_device *dev)
+{
+       int err;
+       if (mei_me_hw_is_ready(dev))
+               return 0;
+
+       mutex_unlock(&dev->device_lock);
+       err = wait_event_interruptible_timeout(dev->wait_hw_ready,
+                       dev->recvd_hw_ready, MEI_INTEROP_TIMEOUT);
+       mutex_lock(&dev->device_lock);
+       if (!err && !dev->recvd_hw_ready) {
+               dev_err(&dev->pdev->dev,
+                       "wait hw ready failed. status = 0x%x\n", err);
+               return -ETIMEDOUT;
+       }
+
+       dev->recvd_hw_ready = false;
+       return 0;
+}
+
+static int mei_me_hw_start(struct mei_device *dev)
+{
+       int ret = mei_me_hw_ready_wait(dev);
+       if (ret)
+               return ret;
+       dev_dbg(&dev->pdev->dev, "hw is ready\n");
+
+       mei_me_host_set_ready(dev);
+       return ret;
+}
+
+
 /**
  * mei_hbuf_filled_slots - gets number of device filled buffer slots
  *
@@ -456,14 +488,9 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
                if (mei_hw_is_ready(dev)) {
                        dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
 
-                       mei_host_set_ready(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;
+                       dev->recvd_hw_ready = true;
+                       wake_up_interruptible(&dev->wait_hw_ready);
 
-                       mei_hbm_start_req(dev);
                        mutex_unlock(&dev->device_lock);
                        return IRQ_HANDLED;
                } else {
@@ -521,12 +548,12 @@ end:
 }
 static const struct mei_hw_ops mei_me_hw_ops = {
 
-       .host_set_ready = mei_me_host_set_ready,
        .host_is_ready = mei_me_host_is_ready,
 
        .hw_is_ready = mei_me_hw_is_ready,
        .hw_reset = mei_me_hw_reset,
-       .hw_config  = mei_me_hw_config,
+       .hw_config = mei_me_hw_config,
+       .hw_start = mei_me_hw_start,
 
        .intr_clear = mei_me_intr_clear,
        .intr_enable = mei_me_intr_enable,
index 6ec530168afbbe2268da06d1c2508fd044cb943d..fc3d97ce83001c20aea9acef3dd23329cf940f35 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/mei.h>
 
 #include "mei_dev.h"
+#include "hbm.h"
 #include "client.h"
 
 const char *mei_dev_state_str(int state)
@@ -47,6 +48,7 @@ void mei_device_init(struct mei_device *dev)
        /* setup our list array */
        INIT_LIST_HEAD(&dev->file_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;
@@ -176,6 +178,20 @@ 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);
 
index 09a2af4294a6275ba28aba96a11785de0febdafa..5c30857e91d5314f66aff47f461976b37775ceba 100644 (file)
@@ -213,11 +213,11 @@ struct mei_cl {
 
 /** struct mei_hw_ops
  *
- * @host_set_ready   - notify FW that host side is ready
  * @host_is_ready    - query for host readiness
 
  * @hw_is_ready      - query if hw is ready
  * @hw_reset         - reset hw
+ * @hw_start         - start hw after reset
  * @hw_config        - configure hw
 
  * @intr_clear       - clear pending interrupts
@@ -237,11 +237,11 @@ struct mei_cl {
  */
 struct mei_hw_ops {
 
-       void (*host_set_ready) (struct mei_device *dev);
        bool (*host_is_ready) (struct mei_device *dev);
 
        bool (*hw_is_ready) (struct mei_device *dev);
        void (*hw_reset) (struct mei_device *dev, bool enable);
+       int  (*hw_start) (struct mei_device *dev);
        void (*hw_config) (struct mei_device *dev);
 
        void (*intr_clear) (struct mei_device *dev);
@@ -296,11 +296,14 @@ struct mei_device {
         */
        struct mutex device_lock; /* device lock */
        struct delayed_work timer_work; /* MEI timer delayed work (timeouts) */
+
+       bool recvd_hw_ready;
        bool recvd_msg;
 
        /*
         * waiting queue for receive message from FW
         */
+       wait_queue_head_t wait_hw_ready;
        wait_queue_head_t wait_recvd_msg;
        wait_queue_head_t wait_stop_wd;
 
@@ -465,6 +468,11 @@ static inline void mei_hw_reset(struct mei_device *dev, bool enable)
        dev->ops->hw_reset(dev, enable);
 }
 
+static inline void mei_hw_start(struct mei_device *dev)
+{
+       dev->ops->hw_start(dev);
+}
+
 static inline void mei_clear_interrupts(struct mei_device *dev)
 {
        dev->ops->intr_clear(dev);
@@ -480,10 +488,6 @@ static inline void mei_disable_interrupts(struct mei_device *dev)
        dev->ops->intr_disable(dev);
 }
 
-static inline void mei_host_set_ready(struct mei_device *dev)
-{
-       dev->ops->host_set_ready(dev);
-}
 static inline bool mei_host_is_ready(struct mei_device *dev)
 {
        return dev->ops->host_is_ready(dev);