From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754496AbcGVM5y (ORCPT ); Fri, 22 Jul 2016 08:57:54 -0400 Received: from mga14.intel.com ([192.55.52.115]:10662 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754461AbcGVM5v (ORCPT ); Fri, 22 Jul 2016 08:57:51 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.28,405,1464678000"; d="scan'208";a="738252133" From: Tomas Winkler To: Greg Kroah-Hartman Cc: Alexander Usyskin , linux-kernel@vger.kernel.org, Tomas Winkler Subject: [char-misc-next 10/12] mei: enqueue consecutive reads Date: Fri, 22 Jul 2016 15:56:27 +0300 Message-Id: <1469192189-29042-11-git-send-email-tomas.winkler@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1469192189-29042-1-git-send-email-tomas.winkler@intel.com> References: <1469192189-29042-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 The FW supports only one pending read per host client, in order to support issuing of consecutive reads the driver queues read requests internally and send them to the firmware after pending one has completed. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler --- drivers/misc/mei/interrupt.c | 3 +++ drivers/misc/mei/main.c | 39 +++++++++++++++++++-------------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 36382d782e20..bf745e03f21e 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -209,6 +209,9 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb, int slots; int ret; + if (!list_empty(&cl->rd_pending)) + return 0; + msg_slots = mei_data2slots(sizeof(struct hbm_flow_control)); slots = mei_hbuf_empty_slots(dev); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index d698ba32357c..650061b6ab9b 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -139,9 +139,8 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, struct mei_cl *cl = file->private_data; struct mei_device *dev; struct mei_cl_cb *cb = NULL; + bool nonblock = !!(file->f_flags & O_NONBLOCK); int rets; - int err; - if (WARN_ON(!cl || !cl->dev)) return -ENODEV; @@ -177,25 +176,29 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, if (*offset > 0) *offset = 0; - err = mei_cl_read_start(cl, length, file); - if (err && err != -EBUSY) { - cl_dbg(dev, cl, "mei start read failure status = %d\n", err); - rets = err; + rets = mei_cl_read_start(cl, length, file); + if (rets && rets != -EBUSY) { + cl_dbg(dev, cl, "mei start read failure status = %d\n", rets); goto out; } - /* synchronized under device mutex */ - if (!waitqueue_active(&cl->rx_wait)) { - if (file->f_flags & O_NONBLOCK) { - rets = -EAGAIN; - goto out; - } + if (nonblock) { + rets = -EAGAIN; + goto out; + } + + if (rets == -EBUSY && + !mei_cl_enqueue_ctrl_wr_cb(cl, length, MEI_FOP_READ, file)) { + rets = -ENOMEM; + goto out; + } + do { mutex_unlock(&dev->device_lock); if (wait_event_interruptible(cl->rx_wait, - (!list_empty(&cl->rd_completed)) || - (!mei_cl_is_connected(cl)))) { + (!list_empty(&cl->rd_completed)) || + (!mei_cl_is_connected(cl)))) { if (signal_pending(current)) return -EINTR; @@ -207,13 +210,9 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, rets = -ENODEV; goto out; } - } - cb = mei_cl_read_cb(cl, file); - if (!cb) { - rets = 0; - goto out; - } + cb = mei_cl_read_cb(cl, file); + } while (!cb); copy_buffer: /* now copy the data to user space */ -- 2.7.4