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: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
3c66618295
commit
0c53357ca4
@@ -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 @@ out:
|
|||||||
*
|
*
|
||||||
* 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,19 +990,15 @@ 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);
|
||||||
wait_event_timeout(cl->wait,
|
wait_event_timeout(cl->wait,
|
||||||
@@ -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)
|
|||||||
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,
|
|||||||
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.
|
||||||
|
|||||||
Reference in New Issue
Block a user