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

mei: use runtime pm in write and read flow

Take rpm token on operation start to initiate rpm resume if needed.
Mark last busy time, release token and advice rpm framework
to try to autosuspend on operation end.
Signed-off-by: NTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: NAlexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 cfe5ab85
......@@ -18,6 +18,7 @@
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include <linux/mei.h>
......@@ -415,6 +416,10 @@ void mei_host_client_init(struct work_struct *work)
dev->reset_count = 0;
mutex_unlock(&dev->device_lock);
pm_runtime_mark_last_busy(&dev->pdev->dev);
dev_dbg(&dev->pdev->dev, "rpm: autosuspend\n");
pm_runtime_autosuspend(&dev->pdev->dev);
}
/**
......@@ -425,6 +430,12 @@ void mei_host_client_init(struct work_struct *work)
*/
bool mei_hbuf_acquire(struct mei_device *dev)
{
if (mei_pg_state(dev) == MEI_PG_ON ||
dev->pg_event == MEI_PG_EVENT_WAIT) {
dev_dbg(&dev->pdev->dev, "device is in pg\n");
return false;
}
if (!dev->hbuf_is_ready) {
dev_dbg(&dev->pdev->dev, "hbuf is not ready\n");
return false;
......@@ -460,9 +471,18 @@ int mei_cl_disconnect(struct mei_cl *cl)
if (cl->state != MEI_FILE_DISCONNECTING)
return 0;
rets = pm_runtime_get(&dev->pdev->dev);
if (rets < 0 && rets != -EINPROGRESS) {
pm_runtime_put_noidle(&dev->pdev->dev);
cl_err(dev, cl, "rpm: get failed %d\n", rets);
return rets;
}
cb = mei_io_cb_init(cl, NULL);
if (!cb)
return -ENOMEM;
if (!cb) {
rets = -ENOMEM;
goto free;
}
cb->fop_type = MEI_FOP_CLOSE;
if (mei_hbuf_acquire(dev)) {
......@@ -494,8 +514,7 @@ int mei_cl_disconnect(struct mei_cl *cl)
cl_err(dev, cl, "wrong status client disconnect.\n");
if (err)
cl_dbg(dev, cl, "wait failed disconnect err=%08x\n",
err);
cl_dbg(dev, cl, "wait failed disconnect err=%d\n", err);
cl_err(dev, cl, "failed to disconnect from FW client.\n");
}
......@@ -503,6 +522,10 @@ int mei_cl_disconnect(struct mei_cl *cl)
mei_io_list_flush(&dev->ctrl_rd_list, cl);
mei_io_list_flush(&dev->ctrl_wr_list, cl);
free:
cl_dbg(dev, cl, "rpm: autosuspend\n");
pm_runtime_mark_last_busy(&dev->pdev->dev);
pm_runtime_put_autosuspend(&dev->pdev->dev);
mei_io_cb_free(cb);
return rets;
}
......@@ -557,6 +580,13 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
dev = cl->dev;
rets = pm_runtime_get(&dev->pdev->dev);
if (rets < 0 && rets != -EINPROGRESS) {
pm_runtime_put_noidle(&dev->pdev->dev);
cl_err(dev, cl, "rpm: get failed %d\n", rets);
return rets;
}
cb = mei_io_cb_init(cl, file);
if (!cb) {
rets = -ENOMEM;
......@@ -596,6 +626,10 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
rets = cl->status;
out:
cl_dbg(dev, cl, "rpm: autosuspend\n");
pm_runtime_mark_last_busy(&dev->pdev->dev);
pm_runtime_put_autosuspend(&dev->pdev->dev);
mei_io_cb_free(cb);
return rets;
}
......@@ -713,23 +747,32 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
return -ENOTTY;
}
rets = pm_runtime_get(&dev->pdev->dev);
if (rets < 0 && rets != -EINPROGRESS) {
pm_runtime_put_noidle(&dev->pdev->dev);
cl_err(dev, cl, "rpm: get failed %d\n", rets);
return rets;
}
cb = mei_io_cb_init(cl, NULL);
if (!cb)
return -ENOMEM;
if (!cb) {
rets = -ENOMEM;
goto out;
}
/* always allocate at least client max message */
length = max_t(size_t, length, dev->me_clients[i].props.max_msg_length);
rets = mei_io_cb_alloc_resp_buf(cb, length);
if (rets)
goto err;
goto out;
cb->fop_type = MEI_FOP_READ;
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;
goto err;
goto out;
}
list_add_tail(&cb->list, &dev->read_list.list);
} else {
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
......@@ -737,9 +780,14 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
cl->read_cb = cb;
return rets;
err:
mei_io_cb_free(cb);
out:
cl_dbg(dev, cl, "rpm: autosuspend\n");
pm_runtime_mark_last_busy(&dev->pdev->dev);
pm_runtime_put_autosuspend(&dev->pdev->dev);
if (rets)
mei_io_cb_free(cb);
return rets;
}
......@@ -776,7 +824,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
return rets;
if (rets == 0) {
cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
return 0;
}
......@@ -856,6 +904,12 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
cl_dbg(dev, cl, "mei_cl_write %d\n", buf->size);
rets = pm_runtime_get(&dev->pdev->dev);
if (rets < 0 && rets != -EINPROGRESS) {
pm_runtime_put_noidle(&dev->pdev->dev);
cl_err(dev, cl, "rpm: get failed %d\n", rets);
return rets;
}
cb->fop_type = MEI_FOP_WRITE;
cb->buf_idx = 0;
......@@ -926,6 +980,10 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
rets = buf->size;
err:
cl_dbg(dev, cl, "rpm: autosuspend\n");
pm_runtime_mark_last_busy(&dev->pdev->dev);
pm_runtime_put_autosuspend(&dev->pdev->dev);
return rets;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册