diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index e6f7180fd8f219fe1c054d4f55f2593f76be0d4a..916625a8f0376c3dadf4e6d87b3c733bb8cc0c13 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -298,110 +298,47 @@ static int mei_amthif_read_start(struct mei_cl *cl, struct file *file) /** * mei_amthif_send_cmd - send amthif command to the ME * - * @dev: the device structure + * @cl: the host client * @cb: mei call back struct * * Return: 0 on success, <0 on failure. - * */ -static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb) +static int mei_amthif_send_cmd(struct mei_cl *cl, struct mei_cl_cb *cb) { - struct mei_msg_hdr mei_hdr; - struct mei_cl *cl; + struct mei_device *dev; int ret; - if (!dev || !cb) + if (!cl->dev || !cb) return -ENODEV; - dev_dbg(dev->dev, "write data to amthif client.\n"); + dev = cl->dev; dev->iamthif_state = MEI_IAMTHIF_WRITING; dev->iamthif_current_cb = cb; dev->iamthif_file_object = cb->file_object; dev->iamthif_canceled = false; - dev->iamthif_msg_buf_size = cb->request_buffer.size; - memcpy(dev->iamthif_msg_buf, cb->request_buffer.data, - cb->request_buffer.size); - cl = &dev->iamthif_cl; - ret = mei_cl_flow_ctrl_creds(cl); + ret = mei_cl_write(cl, cb, false); if (ret < 0) return ret; - cb->fop_type = MEI_FOP_WRITE; - if (ret && mei_hbuf_acquire(dev)) { - ret = 0; - if (cb->request_buffer.size > mei_hbuf_max_len(dev)) { - mei_hdr.length = mei_hbuf_max_len(dev); - mei_hdr.msg_complete = 0; - } else { - mei_hdr.length = cb->request_buffer.size; - mei_hdr.msg_complete = 1; - } - - mei_hdr.host_addr = cl->host_client_id; - mei_hdr.me_addr = cl->me_client_id; - mei_hdr.reserved = 0; - mei_hdr.internal = 0; - dev->iamthif_msg_buf_index += mei_hdr.length; - ret = mei_write_message(dev, &mei_hdr, dev->iamthif_msg_buf); - if (ret) - return ret; - - if (mei_hdr.msg_complete) { - if (mei_cl_flow_ctrl_reduce(cl)) - return -EIO; - cb->status = mei_amthif_read_start(cl, cb->file_object); - list_add_tail(&cb->list, &dev->write_waiting_list.list); - } else { - 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); - } - } else { - - list_add_tail(&cb->list, &dev->write_list.list); - } + if (cb->completed) + cb->status = mei_amthif_read_start(cl, cb->file_object); return 0; } /** - * mei_amthif_write - write amthif data to amthif client + * mei_amthif_run_next_cmd - send next amt command from queue * * @dev: the device structure - * @cb: mei call back struct * * Return: 0 on success, <0 on failure. - * */ -int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb) -{ - if (!dev || !cb) - return -ENODEV; - - cb->fop_type = MEI_FOP_WRITE; - if (!list_empty(&dev->amthif_cmd_list.list) || - dev->iamthif_state != MEI_IAMTHIF_IDLE) { - dev_dbg(dev->dev, - "amthif state = %d\n", dev->iamthif_state); - dev_dbg(dev->dev, "AMTHIF: add cb to the wait list\n"); - list_add_tail(&cb->list, &dev->amthif_cmd_list.list); - return 0; - } - return mei_amthif_send_cmd(dev, cb); -} -/** - * mei_amthif_run_next_cmd - send next amt command from queue - * - * @dev: the device structure - */ -void mei_amthif_run_next_cmd(struct mei_device *dev) +int mei_amthif_run_next_cmd(struct mei_device *dev) { + struct mei_cl *cl = &dev->iamthif_cl; struct mei_cl_cb *cb; - int ret; - - if (!dev) - return; dev->iamthif_msg_buf_size = 0; dev->iamthif_msg_buf_index = 0; @@ -415,13 +352,37 @@ void mei_amthif_run_next_cmd(struct mei_device *dev) cb = list_first_entry_or_null(&dev->amthif_cmd_list.list, typeof(*cb), list); if (!cb) - return; + return 0; + list_del_init(&cb->list); - ret = mei_amthif_send_cmd(dev, cb); - if (ret) - dev_warn(dev->dev, "amthif write failed status = %d\n", ret); + return mei_amthif_send_cmd(cl, cb); } +/** + * mei_amthif_write - write amthif data to amthif client + * + * @cl: host client + * @cb: mei call back struct + * + * Return: 0 on success, <0 on failure. + */ +int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb) +{ + + struct mei_device *dev; + + if (WARN_ON(!cl || !cl->dev)) + return -ENODEV; + + if (WARN_ON(!cb)) + return -EINVAL; + + dev = cl->dev; + + cb->fop_type = MEI_FOP_WRITE; + list_add_tail(&cb->list, &dev->amthif_cmd_list.list); + return mei_amthif_run_next_cmd(dev); +} unsigned int mei_amthif_poll(struct mei_device *dev, struct file *file, poll_table *wait) @@ -461,65 +422,14 @@ unsigned int mei_amthif_poll(struct mei_device *dev, int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list) { - struct mei_device *dev = cl->dev; - struct mei_msg_hdr mei_hdr; - size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index; - u32 msg_slots = mei_data2slots(len); - int slots; - int rets; - - rets = mei_cl_flow_ctrl_creds(cl); - if (rets < 0) - return rets; - - if (rets == 0) { - cl_dbg(dev, cl, "No flow control credentials: not sending.\n"); - return 0; - } - - mei_hdr.host_addr = cl->host_client_id; - mei_hdr.me_addr = cl->me_client_id; - mei_hdr.reserved = 0; - mei_hdr.internal = 0; - - slots = mei_hbuf_empty_slots(dev); - - if (slots >= msg_slots) { - mei_hdr.length = len; - mei_hdr.msg_complete = 1; - /* Split the message only if we can write the whole host buffer */ - } else if (slots == dev->hbuf_depth) { - msg_slots = slots; - len = (slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); - mei_hdr.length = len; - mei_hdr.msg_complete = 0; - } else { - /* wait for next time the host buffer is empty */ - return 0; - } - - dev_dbg(dev->dev, MEI_HDR_FMT, MEI_HDR_PRM(&mei_hdr)); - - rets = mei_write_message(dev, &mei_hdr, - dev->iamthif_msg_buf + dev->iamthif_msg_buf_index); - if (rets) { - dev->iamthif_state = MEI_IAMTHIF_IDLE; - cl->status = rets; - list_del(&cb->list); - return rets; - } - - if (mei_cl_flow_ctrl_reduce(cl)) - return -EIO; + int ret; - dev->iamthif_msg_buf_index += mei_hdr.length; - cl->status = 0; + ret = mei_cl_irq_write(cl, cb, cmpl_list); + if (ret) + return ret; - if (mei_hdr.msg_complete) { + if (cb->completed) cb->status = mei_amthif_read_start(cl, cb->file_object); - list_move_tail(&cb->list, &dev->write_waiting_list.list); - } - return 0; } diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 3e9cf0db5540251d1adf48f181d687650156adb2..d9f4e28ac972162a366b9e34ec583a6f0af37618 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1106,6 +1106,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, cl->status = 0; cl->writing_state = MEI_WRITING; cb->buf_idx += mei_hdr.length; + cb->completed = mei_hdr.msg_complete == 1; if (mei_hdr.msg_complete) { if (mei_cl_flow_ctrl_reduce(cl)) @@ -1194,6 +1195,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking) cl->writing_state = MEI_WRITING; cb->buf_idx = mei_hdr.length; + cb->completed = mei_hdr.msg_complete == 1; out: if (mei_hdr.msg_complete) { diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index cbdbf4af2bf7d76aa63a8a4a740d1bbbcbf947d5..9d1a8cba81c9cb5f17f88a93fac06339c2cf07d3 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -401,7 +401,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, } if (cl == &dev->iamthif_cl) { - rets = mei_amthif_write(dev, write_cb); + rets = mei_amthif_write(cl, write_cb); if (rets) { dev_err(dev->dev, diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index fc460af131d461464afbf91146f0da0edb0f514a..2f2242f1bed1e2838c43edb7ac93c8d2c53f571f 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -201,6 +201,7 @@ struct mei_cl; * @file_object: pointer to file structure * @status: io status of the cb * @internal: communication between driver and FW flag + * @completed: the transfer or reception has completed */ struct mei_cl_cb { struct list_head list; @@ -213,6 +214,7 @@ struct mei_cl_cb { struct file *file_object; int status; u32 internal:1; + u32 completed:1; }; /** @@ -662,8 +664,6 @@ void mei_amthif_reset_params(struct mei_device *dev); int mei_amthif_host_init(struct mei_device *dev); -int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *priv_cb); - int mei_amthif_read(struct mei_device *dev, struct file *file, char __user *ubuf, size_t length, loff_t *offset); @@ -675,8 +675,8 @@ int mei_amthif_release(struct mei_device *dev, struct file *file); struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, struct file *file); -void mei_amthif_run_next_cmd(struct mei_device *dev); - +int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb); +int mei_amthif_run_next_cmd(struct mei_device *dev); int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list);