return false;
}
+int mei_hbm_start_wait(struct mei_device *dev)
+{
+ int ret;
+ if (dev->hbm_state > MEI_HBM_START)
+ return 0;
+
+ 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,
+ mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT));
+ mutex_lock(&dev->device_lock);
+
+ if (ret <= 0 && (dev->hbm_state <= MEI_HBM_START)) {
+ dev->hbm_state = MEI_HBM_IDLE;
+ dev_err(&dev->pdev->dev, "wating for mei start failed\n");
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
/**
* mei_hbm_start_req - sends start request message.
*
* @dev: the device structure
*/
-void mei_hbm_start_req(struct mei_device *dev)
+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;
start_req->host_version.major_version = HBM_MAJOR_VERSION;
start_req->host_version.minor_version = HBM_MINOR_VERSION;
- dev->recvd_msg = false;
+ dev->hbm_state = MEI_HBM_IDLE;
if (mei_write_message(dev, mei_hdr, dev->wr_msg.data)) {
dev_err(&dev->pdev->dev, "version message writet failed\n");
dev->dev_state = MEI_DEV_RESETING;
mei_reset(dev, 1);
+ return -ENODEV;
}
- dev->init_clients_state = MEI_START_MESSAGE;
+ dev->hbm_state = MEI_HBM_START;
dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
- return ;
+ return 0;
}
-/**
+/*
* mei_hbm_enum_clients_req - sends enumeration client request message.
*
* @dev: the device structure
dev_err(&dev->pdev->dev, "enumeration request write failed.\n");
mei_reset(dev, 1);
}
- dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE;
+ dev->hbm_state = MEI_HBM_ENUM_CLIENTS;
dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
return;
}
/* We got all client properties */
if (next_client_index == MEI_CLIENTS_MAX) {
+ dev->hbm_state = MEI_HBM_STARTED;
schedule_work(&dev->init_work);
return 0;
dev->version = version_res->me_max_version;
dev_dbg(&dev->pdev->dev, "version mismatch.\n");
+ dev->hbm_state = MEI_HBM_STOP;
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);
+
return;
}
dev->version.major_version = HBM_MAJOR_VERSION;
dev->version.minor_version = HBM_MINOR_VERSION;
if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
- dev->init_clients_state == MEI_START_MESSAGE) {
+ dev->hbm_state == MEI_HBM_START) {
dev->init_clients_timer = 0;
mei_hbm_enum_clients_req(dev);
} else {
- dev->recvd_msg = false;
dev_err(&dev->pdev->dev, "reset: wrong host start response\n");
mei_reset(dev, 1);
return;
}
- dev->recvd_msg = true;
+ wake_up_interruptible(&dev->wait_recvd_msg);
dev_dbg(&dev->pdev->dev, "host start response message received.\n");
break;
}
if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
- dev->init_clients_state != MEI_CLIENT_PROPERTIES_MESSAGE) {
+ dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) {
dev_err(&dev->pdev->dev, "reset: unexpected properties response\n");
mei_reset(dev, 1);
enum_res = (struct hbm_host_enum_response *) mei_msg;
memcpy(dev->me_clients_map, enum_res->valid_addresses, 32);
if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
- dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) {
+ dev->hbm_state == MEI_HBM_ENUM_CLIENTS) {
dev->init_clients_timer = 0;
dev->me_client_presentation_num = 0;
dev->me_client_index = 0;
mei_hbm_me_cl_allocate(dev);
- dev->init_clients_state =
- MEI_CLIENT_PROPERTIES_MESSAGE;
+ dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
/* first property reqeust */
mei_hbm_prop_req(dev);
break;
case HOST_STOP_RES_CMD:
+
+ 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);
case ME_STOP_REQ_CMD:
+ dev->hbm_state = MEI_HBM_STOP;
mei_hbm_stop_req_prepare(dev, &dev->wr_ext_msg.hdr,
dev->wr_ext_msg.data);
break;
#ifndef _MEI_HBM_H_
#define _MEI_HBM_H_
+struct mei_device;
+struct mei_msg_hdr;
+struct mei_cl;
+
+/**
+ * enum mei_hbm_state - host bus message protocol state
+ *
+ * @MEI_HBM_IDLE : protocol not started
+ * @MEI_HBM_START : start request message was sent
+ * @MEI_HBM_ENUM_CLIENTS : enumeration request was sent
+ * @MEI_HBM_CLIENT_PROPERTIES : acquiring clients properties
+ */
+enum mei_hbm_state {
+ MEI_HBM_IDLE = 0,
+ MEI_HBM_START,
+ MEI_HBM_ENUM_CLIENTS,
+ MEI_HBM_CLIENT_PROPERTIES,
+ MEI_HBM_STARTED,
+ MEI_HBM_STOP,
+};
+
void 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)
hdr->reserved = 0;
}
-void mei_hbm_start_req(struct mei_device *dev);
-
+int mei_hbm_start_req(struct mei_device *dev);
+int mei_hbm_start_wait(struct mei_device *dev);
int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl);
int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl);
int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl);
struct mei_cl_cb complete_list;
s32 slots;
int rets;
- bool bus_message_received;
-
dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
/* initialize our complete list */
dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
- bus_message_received = false;
- if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
- dev_dbg(&dev->pdev->dev, "received waiting bus message\n");
- bus_message_received = true;
- }
mutex_unlock(&dev->device_lock);
- if (bus_message_received) {
- dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n");
- wake_up_interruptible(&dev->wait_recvd_msg);
- bus_message_received = false;
- }
mei_irq_compl_handler(dev, &complete_list);
*/
int mei_start(struct mei_device *dev)
{
- int ret = 0;
-
mutex_lock(&dev->device_lock);
/* acknowledge interrupt and stop interupts */
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;
goto err;
}
- dev->recvd_msg = false;
dev_dbg(&dev->pdev->dev, "link layer has been established.\n");
mutex_unlock(&dev->device_lock);
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 &&
if (dev->dev_state == MEI_DEV_INIT_CLIENTS) {
if (dev->init_clients_timer) {
if (--dev->init_clients_timer == 0) {
- dev_err(&dev->pdev->dev, "reset: init clients timeout ,init clients state = %d.\n",
- dev->init_clients_state);
+ dev_err(&dev->pdev->dev, "reset: init clients timeout hbm_state = %d.\n",
+ dev->hbm_state);
mei_reset(dev, 1);
}
}
*
* @inode: pointer to inode structure
* @file: pointer to file structure
- *
+ e
* returns 0 on success, <0 on error
*/
static int mei_open(struct inode *inode, struct file *file)
#include "hw.h"
#include "hw-me-regs.h"
+#include "hbm.h"
/*
* watch dog definition
const char *mei_dev_state_str(int state);
-/* init clients states*/
-enum mei_init_clients_states {
- MEI_START_MESSAGE = 0,
- MEI_ENUM_CLIENTS_MESSAGE,
- MEI_CLIENT_PROPERTIES_MESSAGE
-};
-
enum iamthif_states {
MEI_IAMTHIF_IDLE,
MEI_IAMTHIF_WRITING,
/**
* struct mei_device - MEI private device struct
+ * @hbm_state - state of host bus message protocol
* @mem_addr - mem mapped base register address
* @hbuf_depth - depth of hardware host/write buffer is slots
struct delayed_work timer_work; /* MEI timer delayed work (timeouts) */
bool recvd_hw_ready;
- bool recvd_msg;
-
/*
* waiting queue for receive message from FW
*/
* mei device states
*/
enum mei_dev_state dev_state;
- enum mei_init_clients_states init_clients_state;
+ enum mei_hbm_state hbm_state;
u16 init_clients_timer;
unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; /* control messages */