[char-misc-next 11/18] mei: iamthif: use client write functions

From: Tomas Winkler
Date: Tue Feb 10 2015 - 03:41:27 EST


Reduce code duplication in amthif code by reusing
regular client write functions.
Add completed flag to cb so amthif client can add
rx credits on write completion

Signed-off-by: Tomas Winkler <tomas.winkler@xxxxxxxxx>
---
drivers/misc/mei/amthif.c | 178 +++++++++++----------------------------------
drivers/misc/mei/client.c | 2 +
drivers/misc/mei/main.c | 2 +-
drivers/misc/mei/mei_dev.h | 8 +-
4 files changed, 51 insertions(+), 139 deletions(-)

diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index e6f7180fd8f2..916625a8f037 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -298,110 +298,47 @@ err:
/**
* 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 e9135246c00e..978f7f95d66d 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 cbdbf4af2bf7..9d1a8cba81c9 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 fc460af131d4..2f2242f1bed1 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);

--
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/