提交 c54bf3ab 编写于 作者: T Tomas Winkler 提交者: Greg Kroah-Hartman

mei: iamthif: send flow control as a regular client

Reuse common client mechanism for sending flow control
hbm message. Add new function mei_amthif_read_start
similar to mei_cl_read_start that puts control flow request
onto the control write queue and drop mei_amthif_irq_read function
Signed-off-by: NTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 4e097bc5
...@@ -254,6 +254,47 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, ...@@ -254,6 +254,47 @@ int mei_amthif_read(struct mei_device *dev, struct file *file,
return rets; return rets;
} }
/**
* mei_amthif_read_start - queue message for sending read credential
*
* @cl: host client
* @file: file pointer of message recipient
*
* Return: 0 on success, <0 on failure.
*/
static int mei_amthif_read_start(struct mei_cl *cl, struct file *file)
{
struct mei_device *dev = cl->dev;
struct mei_cl_cb *cb;
size_t length = dev->iamthif_mtu;
int rets;
cb = mei_io_cb_init(cl, file);
if (!cb) {
rets = -ENOMEM;
goto err;
}
rets = mei_io_cb_alloc_resp_buf(cb, length);
if (rets)
goto err;
cb->fop_type = MEI_FOP_READ;
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
dev->iamthif_msg_buf_index = 0;
dev->iamthif_msg_buf_size = 0;
dev->iamthif_state = MEI_IAMTHIF_READING;
dev->iamthif_file_object = cb->file_object;
dev->iamthif_current_cb = cb;
return 0;
err:
mei_io_cb_free(cb);
return rets;
}
/** /**
* mei_amthif_send_cmd - send amthif command to the ME * mei_amthif_send_cmd - send amthif command to the ME
* *
...@@ -287,6 +328,7 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb) ...@@ -287,6 +328,7 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
if (ret < 0) if (ret < 0)
return ret; return ret;
cb->fop_type = MEI_FOP_WRITE;
if (ret && mei_hbuf_acquire(dev)) { if (ret && mei_hbuf_acquire(dev)) {
ret = 0; ret = 0;
if (cb->request_buffer.size > mei_hbuf_max_len(dev)) { if (cb->request_buffer.size > mei_hbuf_max_len(dev)) {
...@@ -309,19 +351,17 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb) ...@@ -309,19 +351,17 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
if (mei_hdr.msg_complete) { if (mei_hdr.msg_complete) {
if (mei_cl_flow_ctrl_reduce(cl)) if (mei_cl_flow_ctrl_reduce(cl))
return -EIO; return -EIO;
dev->iamthif_flow_control_pending = true; cb->status = mei_amthif_read_start(cl, cb->file_object);
dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
dev_dbg(dev->dev, "add amthif cb to write waiting list\n");
dev->iamthif_current_cb = cb;
dev->iamthif_file_object = cb->file_object;
list_add_tail(&cb->list, &dev->write_waiting_list.list); list_add_tail(&cb->list, &dev->write_waiting_list.list);
} else { } else {
dev_dbg(dev->dev, "message does not complete, so add amthif cb to write list.\n"); dev_dbg(dev->dev, "message does not complete, so add amthif cb to write list.\n");
list_add_tail(&cb->list, &dev->write_list.list); list_add_tail(&cb->list, &dev->write_list.list);
} }
} else { } else {
list_add_tail(&cb->list, &dev->write_list.list); list_add_tail(&cb->list, &dev->write_list.list);
} }
return 0; return 0;
} }
...@@ -336,17 +376,10 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb) ...@@ -336,17 +376,10 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
*/ */
int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb) int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
{ {
int ret;
if (!dev || !cb) if (!dev || !cb)
return -ENODEV; return -ENODEV;
ret = mei_io_cb_alloc_resp_buf(cb, dev->iamthif_mtu);
if (ret)
return ret;
cb->fop_type = MEI_FOP_WRITE; cb->fop_type = MEI_FOP_WRITE;
if (!list_empty(&dev->amthif_cmd_list.list) || if (!list_empty(&dev->amthif_cmd_list.list) ||
dev->iamthif_state != MEI_IAMTHIF_IDLE) { dev->iamthif_state != MEI_IAMTHIF_IDLE) {
dev_dbg(dev->dev, dev_dbg(dev->dev,
...@@ -383,7 +416,7 @@ void mei_amthif_run_next_cmd(struct mei_device *dev) ...@@ -383,7 +416,7 @@ void mei_amthif_run_next_cmd(struct mei_device *dev)
typeof(*cb), list); typeof(*cb), list);
if (!cb) if (!cb)
return; return;
list_del(&cb->list); list_del_init(&cb->list);
ret = mei_amthif_send_cmd(dev, cb); ret = mei_amthif_send_cmd(dev, cb);
if (ret) if (ret)
dev_warn(dev->dev, "amthif write failed status = %d\n", ret); dev_warn(dev->dev, "amthif write failed status = %d\n", ret);
...@@ -483,13 +516,7 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, ...@@ -483,13 +516,7 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
cl->status = 0; cl->status = 0;
if (mei_hdr.msg_complete) { if (mei_hdr.msg_complete) {
dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL; cb->status = mei_amthif_read_start(cl, cb->file_object);
dev->iamthif_flow_control_pending = true;
/* save iamthif cb sent to amthif client */
cb->buf_idx = dev->iamthif_msg_buf_index;
dev->iamthif_current_cb = cb;
list_move_tail(&cb->list, &dev->write_waiting_list.list); list_move_tail(&cb->list, &dev->write_waiting_list.list);
} }
...@@ -505,7 +532,7 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, ...@@ -505,7 +532,7 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
* @mei_hdr: header of amthif message * @mei_hdr: header of amthif message
* @complete_list: completed callbacks list * @complete_list: completed callbacks list
* *
* Return: -ENODEV if cb is NULL 0 otherwise; error message is in cb->status * Return: Always 0; error message is in cb->status
*/ */
int mei_amthif_irq_read_msg(struct mei_cl *cl, int mei_amthif_irq_read_msg(struct mei_cl *cl,
struct mei_msg_hdr *mei_hdr, struct mei_msg_hdr *mei_hdr,
...@@ -514,7 +541,6 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, ...@@ -514,7 +541,6 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl,
struct mei_device *dev; struct mei_device *dev;
struct mei_cl_cb *cb; struct mei_cl_cb *cb;
unsigned char *buffer; unsigned char *buffer;
int ret = 0;
dev = cl->dev; dev = cl->dev;
...@@ -524,10 +550,13 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, ...@@ -524,10 +550,13 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl,
if (dev->iamthif_state != MEI_IAMTHIF_READING) if (dev->iamthif_state != MEI_IAMTHIF_READING)
goto err; goto err;
cb = dev->iamthif_current_cb; list_for_each_entry(cb, &dev->read_list.list, list) {
if (cl == cb->cl)
break;
}
if (!cb) { if (&cb->list == &dev->read_list.list) {
ret = -ENODEV; dev_err(dev->dev, "no reader found\n");
goto err; goto err;
} }
...@@ -553,7 +582,7 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, ...@@ -553,7 +582,7 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl,
cb->read_time = jiffies; cb->read_time = jiffies;
dev_dbg(dev->dev, "complete the amthif read cb.\n "); dev_dbg(dev->dev, "complete the amthif read cb.\n ");
list_add_tail(&cb->list, &complete_list->list); list_move_tail(&cb->list, &complete_list->list);
return 0; return 0;
...@@ -561,38 +590,6 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, ...@@ -561,38 +590,6 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl,
mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length); mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n", dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n",
MEI_HDR_PRM(mei_hdr)); MEI_HDR_PRM(mei_hdr));
return ret;
}
/**
* mei_amthif_irq_read - prepares to read amthif data.
*
* @dev: the device structure.
* @slots: free slots.
*
* Return: 0, OK; otherwise, error.
*/
int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
{
u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
if (*slots < msg_slots)
return -EMSGSIZE;
*slots -= msg_slots;
if (mei_hbm_cl_flow_control_req(dev, &dev->iamthif_cl)) {
dev_dbg(dev->dev, "iamthif flow control failed\n");
return -EIO;
}
dev_dbg(dev->dev, "iamthif flow control success\n");
dev->iamthif_state = MEI_IAMTHIF_READING;
dev->iamthif_flow_control_pending = false;
dev->iamthif_msg_buf_index = 0;
dev->iamthif_msg_buf_size = 0;
dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
return 0; return 0;
} }
...@@ -604,17 +601,32 @@ int mei_amthif_irq_read(struct mei_device *dev, s32 *slots) ...@@ -604,17 +601,32 @@ int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
*/ */
void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb) void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
{ {
if (cb->fop_type == MEI_FOP_WRITE) {
if (!cb->status) {
dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
mei_io_cb_free(cb);
return;
}
/*
* in case of error enqueue the write cb to complete read list
* so it can be propagated to the reader
*/
list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list);
wake_up_interruptible(&dev->iamthif_cl.wait);
return;
}
if (dev->iamthif_canceled != 1) { if (dev->iamthif_canceled != 1) {
dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE; dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
dev->iamthif_stall_timer = 0; dev->iamthif_stall_timer = 0;
memcpy(cb->response_buffer.data, memcpy(cb->response_buffer.data,
dev->iamthif_msg_buf, dev->iamthif_msg_buf, dev->iamthif_msg_buf_index);
dev->iamthif_msg_buf_index);
list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list); list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list);
dev_dbg(dev->dev, "amthif read completed\n"); dev_dbg(dev->dev, "amthif read completed\n");
dev->iamthif_timer = jiffies; dev->iamthif_timer = jiffies;
dev_dbg(dev->dev, "dev->iamthif_timer = %ld\n", dev_dbg(dev->dev, "dev->iamthif_timer = %ld\n",
dev->iamthif_timer); dev->iamthif_timer);
} else { } else {
mei_amthif_run_next_cmd(dev); mei_amthif_run_next_cmd(dev);
} }
......
...@@ -43,7 +43,7 @@ void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list) ...@@ -43,7 +43,7 @@ void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list)
list_for_each_entry_safe(cb, next, &compl_list->list, list) { list_for_each_entry_safe(cb, next, &compl_list->list, list) {
cl = cb->cl; cl = cb->cl;
list_del(&cb->list); list_del_init(&cb->list);
dev_dbg(dev->dev, "completing call back.\n"); dev_dbg(dev->dev, "completing call back.\n");
if (cl == &dev->iamthif_cl) if (cl == &dev->iamthif_cl)
...@@ -386,11 +386,6 @@ int mei_irq_read_handler(struct mei_device *dev, ...@@ -386,11 +386,6 @@ int mei_irq_read_handler(struct mei_device *dev,
if (cl == &dev->iamthif_cl) { if (cl == &dev->iamthif_cl) {
ret = mei_amthif_irq_read_msg(cl, mei_hdr, cmpl_list); ret = mei_amthif_irq_read_msg(cl, mei_hdr, cmpl_list);
if (ret) {
dev_err(dev->dev, "mei_amthif_irq_read_msg failed = %d\n",
ret);
goto end;
}
} else { } else {
ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list); ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list);
} }
...@@ -448,21 +443,9 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) ...@@ -448,21 +443,9 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
cl = cb->cl; cl = cb->cl;
cl->status = 0; cl->status = 0;
list_del(&cb->list); cl_dbg(dev, cl, "MEI WRITE COMPLETE\n");
if (cb->fop_type == MEI_FOP_WRITE && cl->writing_state = MEI_WRITE_COMPLETE;
cl != &dev->iamthif_cl) { list_move_tail(&cb->list, &cmpl_list->list);
cl_dbg(dev, cl, "MEI WRITE COMPLETE\n");
cl->writing_state = MEI_WRITE_COMPLETE;
list_add_tail(&cb->list, &cmpl_list->list);
}
if (cl == &dev->iamthif_cl) {
cl_dbg(dev, cl, "check iamthif flow control.\n");
if (dev->iamthif_flow_control_pending) {
ret = mei_amthif_irq_read(dev, &slots);
if (ret)
return ret;
}
}
} }
if (dev->wd_state == MEI_WD_STOPPING) { if (dev->wd_state == MEI_WD_STOPPING) {
......
...@@ -487,7 +487,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); ...@@ -487,7 +487,6 @@ const char *mei_pg_state_str(enum mei_pg_state state);
* @iamthif_msg_buf_size : size of current amthif message request buffer * @iamthif_msg_buf_size : size of current amthif message request buffer
* @iamthif_msg_buf_index : current index in amthif message request buffer * @iamthif_msg_buf_index : current index in amthif message request buffer
* @iamthif_state : amthif processor state * @iamthif_state : amthif processor state
* @iamthif_flow_control_pending: amthif waits for flow control
* @iamthif_canceled : current amthif command is canceled * @iamthif_canceled : current amthif command is canceled
* *
* @init_work : work item for the device init * @init_work : work item for the device init
...@@ -586,7 +585,6 @@ struct mei_device { ...@@ -586,7 +585,6 @@ struct mei_device {
u32 iamthif_msg_buf_size; u32 iamthif_msg_buf_size;
u32 iamthif_msg_buf_index; u32 iamthif_msg_buf_index;
enum iamthif_states iamthif_state; enum iamthif_states iamthif_state;
bool iamthif_flow_control_pending;
bool iamthif_canceled; bool iamthif_canceled;
struct work_struct init_work; struct work_struct init_work;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册