提交 46978ada 编写于 作者: A Alexander Usyskin 提交者: Greg Kroah-Hartman

mei: rx flow control counter

Use RX flow control counter in the host client structure to
track the number of simultaneous outstanding reads.
This eliminates search in queues and makes ground for
enabling for parallel read.
Signed-off-by: NAlexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: NTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 e51dfa5a
......@@ -202,6 +202,7 @@ static int mei_amthif_read_start(struct mei_cl *cl, const struct file *file)
return -ENOMEM;
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
cl->rx_flow_ctrl_creds++;
dev->iamthif_state = MEI_IAMTHIF_READING;
cl->fp = cb->fp;
......
......@@ -735,6 +735,7 @@ void mei_cl_set_disconnected(struct mei_cl *cl)
mei_io_list_flush(&dev->ctrl_wr_list, cl);
mei_cl_wake_all(cl);
cl->mei_flow_ctrl_creds = 0;
cl->rx_flow_ctrl_creds = 0;
cl->timer_count = 0;
if (!cl->me_cl)
......@@ -1408,25 +1409,6 @@ int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev)
return 0;
}
/**
* mei_cl_is_read_fc_cb - check if read cb is waiting for flow control
* for given host client
*
* @cl: host client
*
* Return: true, if found at least one cb.
*/
static bool mei_cl_is_read_fc_cb(struct mei_cl *cl)
{
struct mei_device *dev = cl->dev;
struct mei_cl_cb *cb;
list_for_each_entry(cb, &dev->ctrl_wr_list.list, list)
if (cb->fop_type == MEI_FOP_READ && cb->cl == cl)
return true;
return false;
}
/**
* mei_cl_read_start - the start read client message function.
*
......@@ -1450,10 +1432,6 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp)
if (!mei_cl_is_connected(cl))
return -ENODEV;
/* HW currently supports only one pending read */
if (!list_empty(&cl->rd_pending) || mei_cl_is_read_fc_cb(cl))
return -EBUSY;
if (!mei_me_cl_is_active(cl->me_cl)) {
cl_err(dev, cl, "no such me client\n");
return -ENOTTY;
......@@ -1462,12 +1440,18 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp)
if (mei_cl_is_fixed_address(cl))
return 0;
/* HW currently supports only one pending read */
if (cl->rx_flow_ctrl_creds)
return -EBUSY;
/* always allocate at least client max message */
length = max_t(size_t, length, mei_cl_mtu(cl));
cb = mei_cl_alloc_cb(cl, length, MEI_FOP_READ, fp);
if (!cb)
return -ENOMEM;
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
rets = pm_runtime_get(dev->dev);
if (rets < 0 && rets != -EINPROGRESS) {
pm_runtime_put_noidle(dev->dev);
......@@ -1475,16 +1459,15 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp)
goto nortpm;
}
rets = 0;
if (mei_hbuf_acquire(dev)) {
rets = mei_hbm_cl_flow_control_req(dev, cl);
if (rets < 0)
goto out;
list_add_tail(&cb->list, &cl->rd_pending);
} else {
rets = 0;
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
list_move_tail(&cb->list, &cl->rd_pending);
}
cl->rx_flow_ctrl_creds++;
out:
cl_dbg(dev, cl, "rpm: autosuspend\n");
......@@ -1732,6 +1715,9 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
case MEI_FOP_READ:
list_add_tail(&cb->list, &cl->rd_completed);
if (!mei_cl_is_fixed_address(cl) &&
!WARN_ON(!cl->rx_flow_ctrl_creds))
cl->rx_flow_ctrl_creds--;
if (!mei_cl_bus_rx_event(cl))
wake_up_interruptible(&cl->rx_wait);
break;
......
......@@ -203,8 +203,8 @@ struct mei_cl_cb {
* @fp: file associated with client
* @host_client_id: host id
* @mei_flow_ctrl_creds: transmit flow credentials
* @rx_flow_ctrl_creds: receive flow credentials
* @timer_count: watchdog timer for operation completion
* @reserved: reserved for alignment
* @notify_en: notification - enabled/disabled
* @notify_ev: pending notification event
* @writing_state: state of the tx
......@@ -227,8 +227,8 @@ struct mei_cl {
const struct file *fp;
u8 host_client_id;
u8 mei_flow_ctrl_creds;
u8 rx_flow_ctrl_creds;
u8 timer_count;
u8 reserved;
u8 notify_en;
u8 notify_ev;
enum mei_file_transaction_states writing_state;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册