Commit 0c53357c authored by Tomas Winkler's avatar Tomas Winkler Committed by Greg Kroah-Hartman

mei: revamp client connection

Simplify connect state machine by changing the logic around
Connection request in progress - only check if we have a callback in
relevant queue.
Extract common code into mei_cl_send_connect() function
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarAlexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 3c666182
...@@ -436,6 +436,12 @@ int mei_cl_enable_device(struct mei_cl_device *device) ...@@ -436,6 +436,12 @@ int mei_cl_enable_device(struct mei_cl_device *device)
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
if (mei_cl_is_connected(cl)) {
mutex_unlock(&dev->device_lock);
dev_warn(dev->dev, "Already connected");
return -EBUSY;
}
err = mei_cl_connect(cl, NULL); err = mei_cl_connect(cl, NULL);
if (err < 0) { if (err < 0) {
mutex_unlock(&dev->device_lock); mutex_unlock(&dev->device_lock);
......
...@@ -881,27 +881,82 @@ int mei_cl_disconnect(struct mei_cl *cl) ...@@ -881,27 +881,82 @@ int mei_cl_disconnect(struct mei_cl *cl)
* *
* Return: true if other client is connected, false - otherwise. * Return: true if other client is connected, false - otherwise.
*/ */
bool mei_cl_is_other_connecting(struct mei_cl *cl) static bool mei_cl_is_other_connecting(struct mei_cl *cl)
{ {
struct mei_device *dev; struct mei_device *dev;
struct mei_cl *ocl; /* the other client */ struct mei_cl_cb *cb;
if (WARN_ON(!cl || !cl->dev))
return false;
dev = cl->dev; dev = cl->dev;
list_for_each_entry(ocl, &dev->file_list, link) { list_for_each_entry(cb, &dev->ctrl_rd_list.list, list) {
if (ocl->state == MEI_FILE_CONNECTING && if (cb->fop_type == MEI_FOP_CONNECT &&
ocl != cl && cl->me_client_id == cb->cl->me_client_id)
cl->me_client_id == ocl->me_client_id)
return true; return true;
} }
return false; return false;
} }
/**
* mei_cl_send_connect - send connect request
*
* @cl: host client
* @cb: callback block
*
* Return: 0, OK; otherwise, error.
*/
static int mei_cl_send_connect(struct mei_cl *cl, struct mei_cl_cb *cb)
{
struct mei_device *dev;
int ret;
dev = cl->dev;
ret = mei_hbm_cl_connect_req(dev, cl);
cl->status = ret;
if (ret) {
cl->state = MEI_FILE_DISCONNECT_REPLY;
return ret;
}
list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
cl->timer_count = MEI_CONNECT_TIMEOUT;
return 0;
}
/**
* mei_cl_irq_connect - send connect request in irq_thread context
*
* @cl: host client
* @cb: callback block
* @cmpl_list: complete list
*
* Return: 0, OK; otherwise, error.
*/
int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
struct mei_cl_cb *cmpl_list)
{
struct mei_device *dev = cl->dev;
u32 msg_slots;
int slots;
int rets;
msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
slots = mei_hbuf_empty_slots(dev);
if (mei_cl_is_other_connecting(cl))
return 0;
if (slots < msg_slots)
return -EMSGSIZE;
rets = mei_cl_send_connect(cl, cb);
if (rets)
list_move_tail(&cb->list, &cmpl_list->list);
return rets;
}
/** /**
* mei_cl_connect - connect host client to the me one * mei_cl_connect - connect host client to the me one
* *
...@@ -935,18 +990,14 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file) ...@@ -935,18 +990,14 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
if (rets) if (rets)
goto out; goto out;
cl->state = MEI_FILE_CONNECTING;
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
/* run hbuf acquire last so we don't have to undo */ /* run hbuf acquire last so we don't have to undo */
if (!mei_cl_is_other_connecting(cl) && mei_hbuf_acquire(dev)) { if (!mei_cl_is_other_connecting(cl) && mei_hbuf_acquire(dev)) {
cl->state = MEI_FILE_CONNECTING; rets = mei_cl_send_connect(cl, cb);
if (mei_hbm_cl_connect_req(dev, cl)) { if (rets)
rets = -ENODEV;
goto out; goto out;
}
cl->timer_count = MEI_CONNECT_TIMEOUT;
list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
} else {
cl->state = MEI_FILE_INITIALIZING;
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
} }
mutex_unlock(&dev->device_lock); mutex_unlock(&dev->device_lock);
...@@ -957,20 +1008,22 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file) ...@@ -957,20 +1008,22 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
if (!mei_cl_is_connected(cl)) { if (!mei_cl_is_connected(cl)) {
/* something went really wrong */ /* timeout or something went really wrong */
if (!cl->status) if (!cl->status)
cl->status = -EFAULT; cl->status = -EFAULT;
mei_cl_set_disconnected(cl);
} }
rets = cl->status; rets = cl->status;
out: out:
cl_dbg(dev, cl, "rpm: autosuspend\n"); cl_dbg(dev, cl, "rpm: autosuspend\n");
pm_runtime_mark_last_busy(dev->dev); pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev); pm_runtime_put_autosuspend(dev->dev);
mei_io_cb_free(cb); mei_io_cb_free(cb);
if (!mei_cl_is_connected(cl))
mei_cl_set_disconnected(cl);
return rets; return rets;
} }
......
...@@ -103,12 +103,13 @@ static inline bool mei_cl_is_connected(struct mei_cl *cl) ...@@ -103,12 +103,13 @@ static inline bool mei_cl_is_connected(struct mei_cl *cl)
return cl->state == MEI_FILE_CONNECTED; return cl->state == MEI_FILE_CONNECTED;
} }
bool mei_cl_is_other_connecting(struct mei_cl *cl);
int mei_cl_disconnect(struct mei_cl *cl); int mei_cl_disconnect(struct mei_cl *cl);
void mei_cl_set_disconnected(struct mei_cl *cl); void mei_cl_set_disconnected(struct mei_cl *cl);
int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb, int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb,
struct mei_cl_cb *cmpl_list); struct mei_cl_cb *cmpl_list);
int mei_cl_connect(struct mei_cl *cl, struct file *file); int mei_cl_connect(struct mei_cl *cl, struct file *file);
int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
struct mei_cl_cb *cmpl_list);
int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp); int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp);
int mei_cl_irq_read_msg(struct mei_cl *cl, struct mei_msg_hdr *hdr, int mei_cl_irq_read_msg(struct mei_cl *cl, struct mei_msg_hdr *hdr,
struct mei_cl_cb *cmpl_list); struct mei_cl_cb *cmpl_list);
......
...@@ -223,49 +223,6 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb, ...@@ -223,49 +223,6 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
return 0; return 0;
} }
/**
* mei_cl_irq_connect - send connect request in irq_thread context
*
* @cl: client
* @cb: callback block.
* @cmpl_list: complete list.
*
* Return: 0, OK; otherwise, error.
*/
static int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
struct mei_cl_cb *cmpl_list)
{
struct mei_device *dev = cl->dev;
u32 msg_slots;
int slots;
int ret;
msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
slots = mei_hbuf_empty_slots(dev);
if (mei_cl_is_other_connecting(cl))
return 0;
if (slots < msg_slots)
return -EMSGSIZE;
cl->state = MEI_FILE_CONNECTING;
ret = mei_hbm_cl_connect_req(dev, cl);
if (ret) {
cl->status = ret;
cb->buf_idx = 0;
list_del_init(&cb->list);
return ret;
}
list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
cl->timer_count = MEI_CONNECT_TIMEOUT;
return 0;
}
/** /**
* mei_irq_read_handler - bottom half read routine after ISR to * mei_irq_read_handler - bottom half read routine after ISR to
* handle the read processing. * handle the read processing.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment