mei: move write cb to completion on credentials failures
authorAlexander Usyskin <alexander.usyskin@intel.com>
Wed, 14 Dec 2016 15:56:52 +0000 (17:56 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 4 Jan 2017 17:22:44 +0000 (18:22 +0100)
The credentials handling was pushed to the write handlers
but error handling wasn't done properly.
Move write callbacks to completion queue to destroy them
and to notify a blocked writer about the failure

Fixes: 136698e535cd1 (mei: push credentials inside the irq write handler)
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>
drivers/misc/mei/client.c

index 391936c1aa041c5bd925d284aa593e65b5ce1065..b0395601c6ae83340f62cd801531632134b85a7a 100644 (file)
@@ -1541,7 +1541,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 
        rets = first_chunk ? mei_cl_tx_flow_ctrl_creds(cl) : 1;
        if (rets < 0)
-               return rets;
+               goto err;
 
        if (rets == 0) {
                cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
@@ -1575,11 +1575,8 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
                        cb->buf.size, cb->buf_idx);
 
        rets = mei_write_message(dev, &mei_hdr, buf->data + cb->buf_idx);
-       if (rets) {
-               cl->status = rets;
-               list_move_tail(&cb->list, &cmpl_list->list);
-               return rets;
-       }
+       if (rets)
+               goto err;
 
        cl->status = 0;
        cl->writing_state = MEI_WRITING;
@@ -1587,14 +1584,21 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
        cb->completed = mei_hdr.msg_complete == 1;
 
        if (first_chunk) {
-               if (mei_cl_tx_flow_ctrl_creds_reduce(cl))
-                       return -EIO;
+               if (mei_cl_tx_flow_ctrl_creds_reduce(cl)) {
+                       rets = -EIO;
+                       goto err;
+               }
        }
 
        if (mei_hdr.msg_complete)
                list_move_tail(&cb->list, &dev->write_waiting_list.list);
 
        return 0;
+
+err:
+       cl->status = rets;
+       list_move_tail(&cb->list, &cmpl_list->list);
+       return rets;
 }
 
 /**