mei: add mei_hbuf_acquire wrapper
authorTomas Winkler <tomas.winkler@intel.com>
Wed, 19 Feb 2014 15:35:47 +0000 (17:35 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 28 Feb 2014 23:15:56 +0000 (15:15 -0800)
A client has to acquire host buffer
before writing, we add lock like wrapper
to replace the code snippet

if (dev->hbuf_is_ready)
        dev->hbuf_is_ready = false;

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/mei/amthif.c
drivers/misc/mei/client.c
drivers/misc/mei/hw-me.c
drivers/misc/mei/hw-txe.c
drivers/misc/mei/interrupt.c
drivers/misc/mei/mei_dev.h
drivers/misc/mei/wd.c

index 61275e6..e7ba880 100644 (file)
@@ -296,9 +296,8 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
        if (ret < 0)
                return ret;
 
-       if (ret && dev->hbuf_is_ready) {
+       if (ret && mei_hbuf_acquire(dev)) {
                ret = 0;
-               dev->hbuf_is_ready = false;
                if (cb->request_buffer.size > mei_hbuf_max_len(dev)) {
                        mei_hdr.length = mei_hbuf_max_len(dev);
                        mei_hdr.msg_complete = 0;
@@ -330,10 +329,6 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
                        list_add_tail(&cb->list, &dev->write_list.list);
                }
        } else {
-               if (!dev->hbuf_is_ready)
-                       dev_dbg(&dev->pdev->dev, "host buffer is not empty");
-
-               dev_dbg(&dev->pdev->dev, "No flow control credentials, so add iamthif cb to write list.\n");
                list_add_tail(&cb->list, &dev->write_list.list);
        }
        return 0;
index 2df0efa..083179b 100644 (file)
@@ -371,6 +371,23 @@ void mei_host_client_init(struct work_struct *work)
        mutex_unlock(&dev->device_lock);
 }
 
+/**
+ * mei_hbuf_acquire: try to acquire host buffer
+ *
+ * @dev: the device structure
+ * returns true if host buffer was acquired
+ */
+bool mei_hbuf_acquire(struct mei_device *dev)
+{
+       if (!dev->hbuf_is_ready) {
+               dev_dbg(&dev->pdev->dev, "hbuf is not ready\n");
+               return false;
+       }
+
+       dev->hbuf_is_ready = false;
+
+       return true;
+}
 
 /**
  * mei_cl_disconnect - disconnect host client from the me one
@@ -402,8 +419,7 @@ int mei_cl_disconnect(struct mei_cl *cl)
                return -ENOMEM;
 
        cb->fop_type = MEI_FOP_CLOSE;
-       if (dev->hbuf_is_ready) {
-               dev->hbuf_is_ready = false;
+       if (mei_hbuf_acquire(dev)) {
                if (mei_hbm_cl_disconnect_req(dev, cl)) {
                        rets = -ENODEV;
                        cl_err(dev, cl, "failed to disconnect.\n");
@@ -503,9 +519,8 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
 
        cb->fop_type = MEI_FOP_CONNECT;
 
-       if (dev->hbuf_is_ready && !mei_cl_is_other_connecting(cl)) {
-               dev->hbuf_is_ready = false;
-
+       /* run hbuf acquire last so we don't have to undo */
+       if (!mei_cl_is_other_connecting(cl) && mei_hbuf_acquire(dev)) {
                if (mei_hbm_cl_connect_req(dev, cl)) {
                        rets = -ENODEV;
                        goto out;
@@ -663,8 +678,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
                goto err;
 
        cb->fop_type = MEI_FOP_READ;
-       if (dev->hbuf_is_ready) {
-               dev->hbuf_is_ready = false;
+       if (mei_hbuf_acquire(dev)) {
                if (mei_hbm_cl_flow_control_req(dev, cl)) {
                        cl_err(dev, cl, "flow control send failed\n");
                        rets = -ENODEV;
@@ -799,21 +813,29 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
 
 
        cb->fop_type = MEI_FOP_WRITE;
+       cb->buf_idx = 0;
+       cl->writing_state = MEI_IDLE;
+
+       mei_hdr.host_addr = cl->host_client_id;
+       mei_hdr.me_addr = cl->me_client_id;
+       mei_hdr.reserved = 0;
+       mei_hdr.msg_complete = 0;
+       mei_hdr.internal = cb->internal;
 
        rets = mei_cl_flow_ctrl_creds(cl);
        if (rets < 0)
                goto err;
 
-       /* Host buffer is not ready, we queue the request */
-       if (rets == 0 || !dev->hbuf_is_ready) {
-               cb->buf_idx = 0;
-               /* unseting complete will enqueue the cb for write */
-               mei_hdr.msg_complete = 0;
+       if (rets == 0) {
+               cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
+               rets = buf->size;
+               goto out;
+       }
+       if (!mei_hbuf_acquire(dev)) {
+               cl_dbg(dev, cl, "Cannot acquire the host buffer: not sending.\n");
                rets = buf->size;
                goto out;
        }
-
-       dev->hbuf_is_ready = false;
 
        /* Check for a maximum length */
        if (buf->size > mei_hbuf_max_len(dev)) {
@@ -824,12 +846,6 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
                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 = cb->internal;
-
-
        rets = mei_write_message(dev, &mei_hdr, buf->data);
        if (rets)
                goto err;
index 847c9e5..b0c42d6 100644 (file)
@@ -513,6 +513,8 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
                }
        }
 
+       dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
+
        rets = mei_irq_write_handler(dev, &complete_list);
 
        dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
index 49a5ed3..8f5e4be 100644 (file)
@@ -605,7 +605,6 @@ static int mei_txe_write(struct mei_device *dev,
                mei_txe_input_payload_write(dev, i + 1, reg);
        }
 
-       dev->hbuf_is_ready = false;
        /* Set Input-Doorbell */
        mei_txe_input_doorbell_set(hw);
 
@@ -983,20 +982,16 @@ irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id)
                dev->hbuf_is_ready = true;
 
        if (hw->aliveness && dev->hbuf_is_ready) {
-               /* if SeC did not complete reading the written data by host */
-               if (!mei_txe_is_input_ready(dev)) {
-                       dev_dbg(&dev->pdev->dev, "got Input Ready Int, but SEC_IPC_INPUT_STATUS_RDY is 0.\n");
-                       goto end;
-               }
 
+               /* get the real register value */
+               dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
                rets = mei_irq_write_handler(dev, &complete_list);
-               if (rets)
-                       dev_err(&dev->pdev->dev,
-                               "mei_irq_write_handler ret = %d.\n", rets);
+               if (rets && rets != -EMSGSIZE)
+                       dev_err(&dev->pdev->dev, "mei_irq_write_handler ret = %d.\n",
+                               rets);
+               dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
        }
 
-
-
        mei_irq_compl_handler(dev, &complete_list);
 
 end:
index 6c4597e..aed03ef 100644 (file)
@@ -446,10 +446,10 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
        s32 slots;
        int ret;
 
-       if (!mei_hbuf_is_ready(dev)) {
-               dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
+
+       if (!mei_hbuf_acquire(dev))
                return 0;
-       }
+
        slots = mei_hbuf_empty_slots(dev);
        if (slots <= 0)
                return -EMSGSIZE;
index 030b29e..52499bc 100644 (file)
@@ -630,6 +630,8 @@ static inline int mei_count_full_read_slots(struct mei_device *dev)
        return dev->ops->rdbuf_full_slots(dev);
 }
 
+bool mei_hbuf_acquire(struct mei_device *dev);
+
 #if IS_ENABLED(CONFIG_DEBUG_FS)
 int mei_dbgfs_register(struct mei_device *dev, const char *name);
 void mei_dbgfs_deregister(struct mei_device *dev);
index 8c30282..afe976a 100644 (file)
@@ -158,9 +158,8 @@ int mei_wd_stop(struct mei_device *dev)
        if (ret < 0)
                goto out;
 
-       if (ret && dev->hbuf_is_ready) {
+       if (ret && mei_hbuf_acquire(dev)) {
                ret = 0;
-               dev->hbuf_is_ready = false;
 
                if (!mei_wd_send(dev)) {
                        ret = mei_cl_flow_ctrl_reduce(&dev->wd_cl);
@@ -265,8 +264,8 @@ static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
  */
 static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
 {
-       int ret = 0;
        struct mei_device *dev;
+       int ret;
 
        dev = watchdog_get_drvdata(wd_dev);
        if (!dev)
@@ -282,10 +281,12 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
 
        dev->wd_state = MEI_WD_RUNNING;
 
+       ret = mei_cl_flow_ctrl_creds(&dev->wd_cl);
+       if (ret < 0)
+               goto end;
        /* Check if we can send the ping to HW*/
-       if (dev->hbuf_is_ready && mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) {
+       if (ret && mei_hbuf_acquire(dev)) {
 
-               dev->hbuf_is_ready = false;
                dev_dbg(&dev->pdev->dev, "wd: sending ping\n");
 
                if (mei_wd_send(dev)) {
@@ -295,8 +296,7 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
                }
 
                if (mei_cl_flow_ctrl_reduce(&dev->wd_cl)) {
-                       dev_err(&dev->pdev->dev,
-                               "wd: mei_cl_flow_ctrl_reduce() failed.\n");
+                       dev_err(&dev->pdev->dev, "wd: mei_cl_flow_ctrl_reduce() failed.\n");
                        ret = -EIO;
                        goto end;
                }