summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/mei/amthif.c1
-rw-r--r--drivers/misc/mei/client.c40
-rw-r--r--drivers/misc/mei/mei_dev.h4
3 files changed, 16 insertions, 29 deletions
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 26568c5..227fd5a 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -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;
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 05cacc3..ded11de 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -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)
@@ -1409,25 +1410,6 @@ out:
}
/**
- * 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.
*
* @cl: host client
@@ -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;
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index aaefbc8..8bdb280 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -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;