From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756066AbcEXNFz (ORCPT ); Tue, 24 May 2016 09:05:55 -0400 Received: from mga09.intel.com ([134.134.136.24]:43921 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753364AbcEXNFx (ORCPT ); Tue, 24 May 2016 09:05:53 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,359,1459839600"; d="scan'208";a="973477479" From: Tomas Winkler To: Greg Kroah-Hartman Cc: Alexander Usyskin , linux-kernel@vger.kernel.org, Tomas Winkler Subject: [char-misc-next 2/7] mei: amthif: fix request cancel Date: Tue, 24 May 2016 16:03:36 -0400 Message-Id: <1464120221-28151-3-git-send-email-tomas.winkler@intel.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1464120221-28151-1-git-send-email-tomas.winkler@intel.com> References: <1464120221-28151-1-git-send-email-tomas.winkler@intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Alexander Usyskin Currently, all requests cancelled by the user are immediately removed from the queues. Such removal can cause unexpected behavior in the case when a request is partially written or a reply is received after the request is cancelled. To resolve this a request is always fully processed and the result is discarded in case the request was canceled. This completes the partial fix in commit: 9d04ee1 ("mei: amthif: discard not read messages") Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler --- drivers/misc/mei/amthif.c | 111 +++++++++++++++---------------------------- drivers/misc/mei/interrupt.c | 2 - 2 files changed, 38 insertions(+), 75 deletions(-) diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 13d89043ad76..0cded8aa72c0 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -399,34 +399,44 @@ void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb) { struct mei_device *dev = cl->dev; - if (cb->fop_type == MEI_FOP_WRITE) { + dev_dbg(dev->dev, "completing amthif call back.\n"); + switch (cb->fop_type) { + case MEI_FOP_WRITE: if (!cb->status) { dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER; mei_io_cb_free(cb); return; } - /* - * in case of error enqueue the write cb to complete read list - * so it can be propagated to the reader - */ - list_add_tail(&cb->list, &cl->rd_completed); - wake_up_interruptible(&cl->rx_wait); - return; - } + dev->iamthif_current_cb = NULL; + dev->iamthif_state = MEI_IAMTHIF_IDLE; + dev->iamthif_fp = NULL; + if (!dev->iamthif_canceled) { + /* + * in case of error enqueue the write cb to complete + * read list so it can be propagated to the reader + */ + list_add_tail(&cb->list, &cl->rd_completed); + wake_up_interruptible(&cl->rx_wait); + } else { + mei_io_cb_free(cb); + } + break; + case MEI_FOP_READ: + if (!dev->iamthif_canceled) { + list_add_tail(&cb->list, &cl->rd_completed); + dev_dbg(dev->dev, "amthif read completed\n"); + wake_up_interruptible(&cl->rx_wait); + } else { + mei_io_cb_free(cb); + } - if (!dev->iamthif_canceled) { - list_add_tail(&cb->list, &cl->rd_completed); - dev_dbg(dev->dev, "amthif read completed\n"); - } else { - mei_io_cb_free(cb); + dev->iamthif_current_cb = NULL; + dev->iamthif_stall_timer = 0; + mei_amthif_run_next_cmd(dev); + break; + default: + WARN_ON(1); } - - dev->iamthif_current_cb = NULL; - dev->iamthif_stall_timer = 0; - mei_amthif_run_next_cmd(dev); - - dev_dbg(dev->dev, "completing amthif call back.\n"); - wake_up_interruptible(&cl->rx_wait); } /** @@ -439,32 +449,15 @@ void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb) * * mei_clear_list is called to clear resources associated with file * when application calls close function or Ctrl-C was pressed - * - * Return: true if callback removed from the list, false otherwise */ -static bool mei_clear_list(struct mei_device *dev, +static void mei_clear_list(struct mei_device *dev, const struct file *file, struct list_head *mei_cb_list) { - struct mei_cl *cl = &dev->iamthif_cl; struct mei_cl_cb *cb, *next; - bool removed = false; - - /* list all list member */ - list_for_each_entry_safe(cb, next, mei_cb_list, list) { - /* check if list member associated with a file */ - if (file == cb->fp) { - /* check if cb equal to current iamthif cb */ - if (dev->iamthif_current_cb == cb) { - dev->iamthif_current_cb = NULL; - /* send flow control to iamthif client */ - mei_hbm_cl_flow_control_req(dev, cl); - } - /* free all allocated buffers */ + + list_for_each_entry_safe(cb, next, mei_cb_list, list) + if (file == cb->fp) mei_io_cb_free(cb); - removed = true; - } - } - return removed; } /** @@ -475,41 +468,14 @@ static bool mei_clear_list(struct mei_device *dev, * * mei_clear_lists is called to clear resources associated with file * when application calls close function or Ctrl-C was pressed - * - * Return: true if callback removed from the list, false otherwise */ -static bool mei_clear_lists(struct mei_device *dev, const struct file *file) +static void mei_clear_lists(struct mei_device *dev, const struct file *file) { - bool removed = false; struct mei_cl *cl = &dev->iamthif_cl; - /* remove callbacks associated with a file */ mei_clear_list(dev, file, &dev->amthif_cmd_list.list); - if (mei_clear_list(dev, file, &cl->rd_completed)) - removed = true; - + mei_clear_list(dev, file, &cl->rd_completed); mei_clear_list(dev, file, &dev->ctrl_rd_list.list); - - if (mei_clear_list(dev, file, &dev->ctrl_wr_list.list)) - removed = true; - - if (mei_clear_list(dev, file, &dev->write_waiting_list.list)) - removed = true; - - if (mei_clear_list(dev, file, &dev->write_list.list)) - removed = true; - - /* check if iamthif_current_cb not NULL */ - if (dev->iamthif_current_cb && !removed) { - /* check file and iamthif current cb association */ - if (dev->iamthif_current_cb->fp == file) { - /* remove cb */ - mei_io_cb_free(dev->iamthif_current_cb); - dev->iamthif_current_cb = NULL; - removed = true; - } - } - return removed; } /** @@ -533,8 +499,7 @@ int mei_amthif_release(struct mei_device *dev, struct file *file) dev->iamthif_canceled = true; } - if (mei_clear_lists(dev, file)) - dev->iamthif_state = MEI_IAMTHIF_IDLE; + mei_clear_lists(dev, file); return 0; } diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 3831a7ba2531..38db1c3d4f14 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -514,8 +514,6 @@ void mei_timer(struct work_struct *work) if (--dev->iamthif_stall_timer == 0) { dev_err(dev->dev, "timer: amthif hanged.\n"); mei_reset(dev); - dev->iamthif_canceled = false; - dev->iamthif_state = MEI_IAMTHIF_IDLE; mei_io_cb_free(dev->iamthif_current_cb); dev->iamthif_current_cb = NULL; -- 2.5.5