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: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
return -ENOMEM;
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
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;
dev->iamthif_state = MEI_IAMTHIF_READING;
cl->fp = cb->fp;
mei_io_list_flush(&dev->ctrl_wr_list, cl);
mei_cl_wake_all(cl);
cl->mei_flow_ctrl_creds = 0;
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)
cl->timer_count = 0;
if (!cl->me_cl)
-/**
- * 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.
*
/**
* mei_cl_read_start - the start read client message function.
*
if (!mei_cl_is_connected(cl))
return -ENODEV;
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;
if (!mei_me_cl_is_active(cl->me_cl)) {
cl_err(dev, cl, "no such me client\n");
return -ENOTTY;
if (mei_cl_is_fixed_address(cl))
return 0;
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;
/* 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);
rets = pm_runtime_get(dev->dev);
if (rets < 0 && rets != -EINPROGRESS) {
pm_runtime_put_noidle(dev->dev);
if (mei_hbuf_acquire(dev)) {
rets = mei_hbm_cl_flow_control_req(dev, cl);
if (rets < 0)
goto out;
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");
out:
cl_dbg(dev, cl, "rpm: autosuspend\n");
case MEI_FOP_READ:
list_add_tail(&cb->list, &cl->rd_completed);
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;
if (!mei_cl_bus_rx_event(cl))
wake_up_interruptible(&cl->rx_wait);
break;
* @fp: file associated with client
* @host_client_id: host id
* @mei_flow_ctrl_creds: transmit flow credentials
* @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
* @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
* @notify_en: notification - enabled/disabled
* @notify_ev: pending notification event
* @writing_state: state of the tx
const struct file *fp;
u8 host_client_id;
u8 mei_flow_ctrl_creds;
const struct file *fp;
u8 host_client_id;
u8 mei_flow_ctrl_creds;
u8 notify_en;
u8 notify_ev;
enum mei_file_transaction_states writing_state;
u8 notify_en;
u8 notify_ev;
enum mei_file_transaction_states writing_state;