From patchwork Thu May 8 13:32:09 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Archana Patni X-Patchwork-Id: 4133771 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Original-To: patchwork-linux-input@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 42BC19F23C for ; Thu, 8 May 2014 08:24:38 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 72A45202EA for ; Thu, 8 May 2014 08:24:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 97B70202E9 for ; Thu, 8 May 2014 08:24:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751192AbaEHIYf (ORCPT ); Thu, 8 May 2014 04:24:35 -0400 Received: from mga09.intel.com ([134.134.136.24]:21348 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751132AbaEHIYe (ORCPT ); Thu, 8 May 2014 04:24:34 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP; 08 May 2014 01:19:34 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.97,1009,1389772800"; d="scan'208";a="508229615" Received: from inteladmin-virtual-machine.iind.intel.com ([10.223.162.7]) by orsmga001.jf.intel.com with ESMTP; 08 May 2014 01:24:02 -0700 From: Archana Patni To: jkosina@suse.cz Cc: jic23@kernel.org, linux-input@vger.kernel.org, mika.westerberg@intel.com, srinivas.pandruvada@intel.com, Archana Patni , Archana Patni , Subramony Sesha Subject: [PATCH] HID: i2c-hid: Support batch read of input events from fifo Date: Thu, 8 May 2014 09:32:09 -0400 Message-Id: <1399555929-10870-1-git-send-email-archana.patni@linux.intel.com> X-Mailer: git-send-email 1.7.9.5 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Spam-Status: No, score=-4.5 required=5.0 tests=BAYES_00, DATE_IN_FUTURE_03_06, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Some i2c_hid devices like a sensor hub have built-in fifos which can accumulate input events in their buffers and trigger an interrupt at end of a user defined event like fifo full or a timeout. The current implementation reads one event at a time in the IRQ handler leading to several hundred interrupts being necessary to flush the fifo. This patch changes the threaded IRQ handler to keep input events until there are no input events left to read. In the normal case, this will invoke one additional call to fetch an input event to check for no pending events and terminate the loop. Signed-off-by: Archana Patni Signed-off-by: Subramony Sesha Reviewed-by: Mika Westerberg Reviewed-by: Srinivas Pandruvada --- drivers/hid/i2c-hid/i2c-hid.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 21aafc8..3f09a50 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -52,6 +52,7 @@ static bool debug; module_param(debug, bool, 0444); MODULE_PARM_DESC(debug, "print a lot of debug information"); +#define MAX_INPUT_EVENT_READ 100 #define i2c_hid_dbg(ihid, fmt, arg...) \ do { \ @@ -366,7 +367,7 @@ static int i2c_hid_hwreset(struct i2c_client *client) return 0; } -static void i2c_hid_get_input(struct i2c_hid *ihid) +static int i2c_hid_get_input(struct i2c_hid *ihid) { int ret, ret_size; int size = le16_to_cpu(ihid->hdesc.wMaxInputLength); @@ -374,11 +375,11 @@ static void i2c_hid_get_input(struct i2c_hid *ihid) ret = i2c_master_recv(ihid->client, ihid->inbuf, size); if (ret != size) { if (ret < 0) - return; + return ret; dev_err(&ihid->client->dev, "%s: got %d data instead of %d\n", __func__, ret, size); - return; + return -EIO; } ret_size = ihid->inbuf[0] | ihid->inbuf[1] << 8; @@ -387,13 +388,13 @@ static void i2c_hid_get_input(struct i2c_hid *ihid) /* host or device initiated RESET completed */ if (test_and_clear_bit(I2C_HID_RESET_PENDING, &ihid->flags)) wake_up(&ihid->wait); - return; + return 0; } if (ret_size > size) { dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n", __func__, size, ret_size); - return; + return -EIO; } i2c_hid_dbg(ihid, "input: %*ph\n", ret_size, ihid->inbuf); @@ -402,17 +403,22 @@ static void i2c_hid_get_input(struct i2c_hid *ihid) hid_input_report(ihid->hid, HID_INPUT_REPORT, ihid->inbuf + 2, ret_size - 2, 1); - return; + return 1; } static irqreturn_t i2c_hid_irq(int irq, void *dev_id) { struct i2c_hid *ihid = dev_id; + int ret; + int count = 0; if (test_bit(I2C_HID_READ_PENDING, &ihid->flags)) return IRQ_HANDLED; + do { + count++; + ret = i2c_hid_get_input(ihid); - i2c_hid_get_input(ihid); + } while (count < MAX_INPUT_EVENT_READ && ret > 0); return IRQ_HANDLED; }