From patchwork Tue Nov 29 10:08:20 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 9451339 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id BEB3F60235 for ; Tue, 29 Nov 2016 10:10:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A1E612810E for ; Tue, 29 Nov 2016 10:10:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 959822811E; Tue, 29 Nov 2016 10:10:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3FBE32810E for ; Tue, 29 Nov 2016 10:10:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933572AbcK2KKF (ORCPT ); Tue, 29 Nov 2016 05:10:05 -0500 Received: from mx1.redhat.com ([209.132.183.28]:53620 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933391AbcK2KIs (ORCPT ); Tue, 29 Nov 2016 05:08:48 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D9D036A6CA; Tue, 29 Nov 2016 10:08:47 +0000 (UTC) Received: from plouf.banquise.eu (ovpn-116-100.ams2.redhat.com [10.36.116.100]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id uATA8P1u027599; Tue, 29 Nov 2016 05:08:46 -0500 From: Benjamin Tissoires To: Dmitry Torokhov , Jiri Kosina , Andrew Duggan , Lyude Paul , Nick Dyer , Dennis Wassenberg Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 09/13] Input: synaptics-rmi4 - allow to add attention data Date: Tue, 29 Nov 2016 11:08:20 +0100 Message-Id: <1480414104-8524-10-git-send-email-benjamin.tissoires@redhat.com> In-Reply-To: <1480414104-8524-1-git-send-email-benjamin.tissoires@redhat.com> References: <1480414104-8524-1-git-send-email-benjamin.tissoires@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Tue, 29 Nov 2016 10:08:47 +0000 (UTC) Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The HID implementation of RMI4 provides the data during the interrupt (in the input report). We need to provide a way for this transport driver to provide the attention data while calling an IRQ. We use a fifo in rmi_core to not lose any incoming event. Signed-off-by: Benjamin Tissoires --- drivers/input/rmi4/rmi_driver.c | 49 +++++++++++++++++++++++++++++++++++++++-- include/linux/rmi.h | 11 +++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c index a718e51..85062e4 100644 --- a/drivers/input/rmi4/rmi_driver.c +++ b/drivers/input/rmi4/rmi_driver.c @@ -191,16 +191,53 @@ static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev) return 0; } +void rmi_set_attn_data(struct rmi_device *rmi_dev, unsigned long irq_status, + void *data, size_t size) +{ + struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev); + struct rmi4_attn_data attn_data; + void *fifo_data; + + if (!drvdata->enabled) + return; + + fifo_data = kmemdup(data, size, GFP_ATOMIC); + if (!fifo_data) + return; + + attn_data.irq_status = irq_status; + attn_data.size = size; + attn_data.data = fifo_data; + + kfifo_put(&drvdata->attn_fifo, attn_data); +} +EXPORT_SYMBOL_GPL(rmi_set_attn_data); + static irqreturn_t rmi_irq_fn(int irq, void *dev_id) { struct rmi_device *rmi_dev = dev_id; - int ret; + struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev); + struct rmi4_attn_data attn_data = {0}; + int ret, count; + + count = kfifo_get(&drvdata->attn_fifo, &attn_data); + if (count) { + *(drvdata->irq_status) = attn_data.irq_status; + rmi_dev->xport->attn_data = attn_data.data; + rmi_dev->xport->attn_size = attn_data.size; + } ret = rmi_process_interrupt_requests(rmi_dev); if (ret) rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev, "Failed to process interrupt request: %d\n", ret); + if (count) + kfree(attn_data.data); + + if (!kfifo_is_empty(&drvdata->attn_fifo)) + return rmi_irq_fn(irq, dev_id); + return IRQ_HANDLED; } @@ -880,8 +917,9 @@ void rmi_disable_irq(struct rmi_device *rmi_dev, bool enable_wake) { struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev); struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev); + struct rmi4_attn_data attn_data = {0}; int irq = pdata->irq; - int retval; + int retval, count; mutex_lock(&data->enabled_mutex); @@ -898,6 +936,13 @@ void rmi_disable_irq(struct rmi_device *rmi_dev, bool enable_wake) retval); } + /* make sure the fifo is clean */ + while (!kfifo_is_empty(&data->attn_fifo)) { + count = kfifo_get(&data->attn_fifo, &attn_data); + if (count) + kfree(attn_data.data); + } + out: mutex_unlock(&data->enabled_mutex); } diff --git a/include/linux/rmi.h b/include/linux/rmi.h index 7780e40..1d48656 100644 --- a/include/linux/rmi.h +++ b/include/linux/rmi.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -331,6 +332,12 @@ struct rmi_device { }; +struct rmi4_attn_data { + unsigned long irq_status; + size_t size; + void *data; +}; + struct rmi_driver_data { struct list_head function_list; @@ -357,11 +364,15 @@ struct rmi_driver_data { bool enabled; struct mutex enabled_mutex; + DECLARE_KFIFO(attn_fifo, struct rmi4_attn_data, 16); }; int rmi_register_transport_device(struct rmi_transport_dev *xport); void rmi_unregister_transport_device(struct rmi_transport_dev *xport); +void rmi_set_attn_data(struct rmi_device *rmi_dev, unsigned long irq_status, + void *data, size_t size); + int rmi_driver_suspend(struct rmi_device *rmi_dev, bool enable_wake); int rmi_driver_resume(struct rmi_device *rmi_dev, bool clear_wake); #endif