|
@@ -349,6 +349,36 @@ void mei_io_cb_free(struct mei_cl_cb *cb)
|
|
kfree(cb);
|
|
kfree(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
|
|
* mei_io_cb_init - allocate and initialize io callback
|
|
*
|
|
*
|
|
@@ -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
|
|
* @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;
|
|
struct mei_cl_cb *cb, *next;
|
|
|
|
|
|
- /* enable removing everything if no cl is specified */
|
|
|
|
list_for_each_entry_safe(cb, next, head, list) {
|
|
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);
|
|
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
|
|
* @head: An instance of our list structure
|
|
* @cl: host client
|
|
* @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;
|
|
dev = cl->dev;
|
|
|
|
|
|
cl_dbg(dev, cl, "remove list entry belonging to cl\n");
|
|
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_wr_list, cl);
|
|
mei_io_list_flush_cl(&cl->dev->ctrl_rd_list, cl);
|
|
mei_io_list_flush_cl(&cl->dev->ctrl_rd_list, cl);
|
|
mei_io_list_free_fp(&cl->rd_pending, fp);
|
|
mei_io_list_free_fp(&cl->rd_pending, fp);
|
|
@@ -756,8 +774,8 @@ static void mei_cl_set_disconnected(struct mei_cl *cl)
|
|
return;
|
|
return;
|
|
|
|
|
|
cl->state = MEI_FILE_DISCONNECTED;
|
|
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_rd_list, cl);
|
|
mei_io_list_flush_cl(&dev->ctrl_wr_list, cl);
|
|
mei_io_list_flush_cl(&dev->ctrl_wr_list, cl);
|
|
mei_cl_wake_all(cl);
|
|
mei_cl_wake_all(cl);
|
|
@@ -1693,9 +1711,9 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
|
|
|
|
|
|
out:
|
|
out:
|
|
if (mei_hdr.msg_complete)
|
|
if (mei_hdr.msg_complete)
|
|
- list_add_tail(&cb->list, &dev->write_waiting_list);
|
|
|
|
|
|
+ mei_tx_cb_enqueue(cb, &dev->write_waiting_list);
|
|
else
|
|
else
|
|
- list_add_tail(&cb->list, &dev->write_list);
|
|
|
|
|
|
+ mei_tx_cb_enqueue(cb, &dev->write_list);
|
|
|
|
|
|
cb = NULL;
|
|
cb = NULL;
|
|
if (blocking && cl->writing_state != MEI_WRITE_COMPLETE) {
|
|
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) {
|
|
switch (cb->fop_type) {
|
|
case MEI_FOP_WRITE:
|
|
case MEI_FOP_WRITE:
|
|
- mei_io_cb_free(cb);
|
|
|
|
|
|
+ mei_tx_cb_dequeue(cb);
|
|
cl->writing_state = MEI_WRITE_COMPLETE;
|
|
cl->writing_state = MEI_WRITE_COMPLETE;
|
|
if (waitqueue_active(&cl->tx_wait)) {
|
|
if (waitqueue_active(&cl->tx_wait)) {
|
|
wake_up_interruptible(&cl->tx_wait);
|
|
wake_up_interruptible(&cl->tx_wait);
|