summary refs log tree commit diff
path: root/drivers/misc/mei/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/mei/client.c')
-rw-r--r--drivers/misc/mei/client.c82
1 files changed, 50 insertions, 32 deletions
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index bdfb4ecf848a..8d6197a88b54 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -350,6 +350,36 @@ void mei_io_cb_free(struct mei_cl_cb *cb)
 }
 
 /**
+ * mei_tx_cb_queue - queue tx callback
+ *
+ * Locking: called under "dev->device_lock" lock
+ *
+ * @cb: mei callback struct
+ * @head: an instance of list to queue on
+ */
+static inline void mei_tx_cb_enqueue(struct mei_cl_cb *cb,
+				     struct list_head *head)
+{
+	list_add_tail(&cb->list, head);
+	cb->cl->tx_cb_queued++;
+}
+
+/**
+ * mei_tx_cb_dequeue - dequeue tx callback
+ *
+ * Locking: called under "dev->device_lock" lock
+ *
+ * @cb: mei callback struct to dequeue and free
+ */
+static inline void mei_tx_cb_dequeue(struct mei_cl_cb *cb)
+{
+	if (!WARN_ON(cb->cl->tx_cb_queued == 0))
+		cb->cl->tx_cb_queued--;
+
+	mei_io_cb_free(cb);
+}
+
+/**
  * mei_io_cb_init - allocate and initialize io callback
  *
  * @cl: mei client
@@ -377,49 +407,37 @@ static struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl,
 }
 
 /**
- * __mei_io_list_flush_cl - removes and frees cbs belonging to cl.
+ * mei_io_list_flush_cl - removes cbs belonging to the cl.
  *
  * @head:  an instance of our list structure
- * @cl:    host client, can be NULL for flushing the whole list
- * @free:  whether to free the cbs
+ * @cl:    host client
  */
-static void __mei_io_list_flush_cl(struct list_head *head,
-				   const struct mei_cl *cl, bool free)
+static void mei_io_list_flush_cl(struct list_head *head,
+				 const struct mei_cl *cl)
 {
 	struct mei_cl_cb *cb, *next;
 
-	/* enable removing everything if no cl is specified */
 	list_for_each_entry_safe(cb, next, head, list) {
-		if (!cl || mei_cl_cmp_id(cl, cb->cl)) {
+		if (mei_cl_cmp_id(cl, cb->cl))
 			list_del_init(&cb->list);
-			if (free)
-				mei_io_cb_free(cb);
-		}
 	}
 }
 
 /**
- * mei_io_list_flush_cl - removes list entry belonging to cl.
+ * mei_io_tx_list_free_cl - removes cb belonging to the cl and free them
  *
  * @head: An instance of our list structure
  * @cl: host client
  */
-static inline void mei_io_list_flush_cl(struct list_head *head,
-					const struct mei_cl *cl)
+static void mei_io_tx_list_free_cl(struct list_head *head,
+				   const struct mei_cl *cl)
 {
-	__mei_io_list_flush_cl(head, cl, false);
-}
+	struct mei_cl_cb *cb, *next;
 
-/**
- * mei_io_list_free_cl - removes cb belonging to cl and free them
- *
- * @head: An instance of our list structure
- * @cl: host client
- */
-static inline void mei_io_list_free_cl(struct list_head *head,
-				       const struct mei_cl *cl)
-{
-	__mei_io_list_flush_cl(head, cl, true);
+	list_for_each_entry_safe(cb, next, head, list) {
+		if (mei_cl_cmp_id(cl, cb->cl))
+			mei_tx_cb_dequeue(cb);
+	}
 }
 
 /**
@@ -538,8 +556,8 @@ int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp)
 	dev = cl->dev;
 
 	cl_dbg(dev, cl, "remove list entry belonging to cl\n");
-	mei_io_list_free_cl(&cl->dev->write_list, cl);
-	mei_io_list_free_cl(&cl->dev->write_waiting_list, cl);
+	mei_io_tx_list_free_cl(&cl->dev->write_list, cl);
+	mei_io_tx_list_free_cl(&cl->dev->write_waiting_list, cl);
 	mei_io_list_flush_cl(&cl->dev->ctrl_wr_list, cl);
 	mei_io_list_flush_cl(&cl->dev->ctrl_rd_list, cl);
 	mei_io_list_free_fp(&cl->rd_pending, fp);
@@ -756,8 +774,8 @@ static void mei_cl_set_disconnected(struct mei_cl *cl)
 		return;
 
 	cl->state = MEI_FILE_DISCONNECTED;
-	mei_io_list_free_cl(&dev->write_list, cl);
-	mei_io_list_free_cl(&dev->write_waiting_list, cl);
+	mei_io_tx_list_free_cl(&dev->write_list, cl);
+	mei_io_tx_list_free_cl(&dev->write_waiting_list, cl);
 	mei_io_list_flush_cl(&dev->ctrl_rd_list, cl);
 	mei_io_list_flush_cl(&dev->ctrl_wr_list, cl);
 	mei_cl_wake_all(cl);
@@ -1693,9 +1711,9 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
 
 out:
 	if (mei_hdr.msg_complete)
-		list_add_tail(&cb->list, &dev->write_waiting_list);
+		mei_tx_cb_enqueue(cb, &dev->write_waiting_list);
 	else
-		list_add_tail(&cb->list, &dev->write_list);
+		mei_tx_cb_enqueue(cb, &dev->write_list);
 
 	cb = NULL;
 	if (blocking && cl->writing_state != MEI_WRITE_COMPLETE) {
@@ -1741,7 +1759,7 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
 
 	switch (cb->fop_type) {
 	case MEI_FOP_WRITE:
-		mei_io_cb_free(cb);
+		mei_tx_cb_dequeue(cb);
 		cl->writing_state = MEI_WRITE_COMPLETE;
 		if (waitqueue_active(&cl->tx_wait)) {
 			wake_up_interruptible(&cl->tx_wait);