Skip to content

Commit

Permalink
mei: add hw start callback
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Tomas Winkler authored and Greg Kroah-Hartman committed Mar 15, 2013
1 parent c8c8d08 commit aafae7e
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 15 deletions.
45 changes: 36 additions & 9 deletions drivers/misc/mei/hw-me.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -521,12 +548,12 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
}
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,
Expand Down
16 changes: 16 additions & 0 deletions drivers/misc/mei/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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);

Expand Down
16 changes: 10 additions & 6 deletions drivers/misc/mei/mei_dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit aafae7e

Please sign in to comment.