From patchwork Wed Aug 24 23:24:34 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 74638 Delivered-To: patch@linaro.org Received: by 10.140.29.52 with SMTP id a49csp557956qga; Wed, 24 Aug 2016 16:25:53 -0700 (PDT) X-Received: by 10.66.142.105 with SMTP id rv9mr10482532pab.33.1472081148816; Wed, 24 Aug 2016 16:25:48 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id sc6si11881380pac.196.2016.08.24.16.25.48; Wed, 24 Aug 2016 16:25:48 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755047AbcHXXZm (ORCPT + 27 others); Wed, 24 Aug 2016 19:25:42 -0400 Received: from mail-oi0-f68.google.com ([209.85.218.68]:35166 "EHLO mail-oi0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933087AbcHXXYp (ORCPT ); Wed, 24 Aug 2016 19:24:45 -0400 Received: by mail-oi0-f68.google.com with SMTP id e80so3055566oig.2; Wed, 24 Aug 2016 16:24:44 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=YUed6lXbDbDM8zsLz7we5rD6t+f7uwOK1dylVF2Hevw=; b=P7MQjJMtwXSOf3ig2aB7Gosajy1IT+WcOFszuvu+wfgbYrMGXuijQwpoIz12S5LMrq Nu+PkC2hhXX1ry/xIxBxqchQrYwaiVBD3DWxdMrG8CkFPfpKIpjsIWgqthF4CQuKfAOd ZtWtIWiAMOZ1EoeSKjUun39IXpuzVFs2V8MiXYWLuDqFfyCQIEF1HTBi8QXeX0WHiaNR f7zaJ4lG47vIXhFqiKFScgXGSqgwdWKVgbuihhpW8ywLMnXmLVoSlhIcWxzmXB5kaBkk a4KBR+hITxvHd76Aj1wmA6qVYO1/AdWfJFnqCIt1GDnTgOd4s9OlFyZsl4hgmXA1nvyL oI7Q== X-Gm-Message-State: AE9vXwObZ1yu/wpSiLH00teEhun7P0bpDhA8wVfLrYGYnLfF2Fmo/2rpi2bk019YJv1SjQ== X-Received: by 10.157.60.107 with SMTP id j40mr4613723ote.9.1472081084161; Wed, 24 Aug 2016 16:24:44 -0700 (PDT) Received: from rob-hp-laptop.herring.priv (72-48-98-129.dyn.grandenetworks.net. [72.48.98.129]) by smtp.googlemail.com with ESMTPSA id a5sm1322910oii.3.2016.08.24.16.24.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 24 Aug 2016 16:24:43 -0700 (PDT) From: Rob Herring To: Greg Kroah-Hartman , Marcel Holtmann , Jiri Slaby , Sebastian Reichel , Arnd Bergmann , "Dr . H . Nikolaus Schaller" , Alan Cox Cc: Loic Poulain , Pavel Machek , Peter Hurley , NeilBrown , Linus Walleij , linux-bluetooth@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 3/6] serio: add buffer receive and write functions Date: Wed, 24 Aug 2016 18:24:34 -0500 Message-Id: <20160824232437.9446-5-robh@kernel.org> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20160824232437.9446-1-robh@kernel.org> References: <20160824232437.9446-1-robh@kernel.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Currently, serio only supports a character at a time receive and write functions. In order to support higher speed protocols like bluetooth, buffer at a time functions are needed. This mirrors the tty ldisc interface for write and receive_buf. Now that a whole buffer can be queued, we need to be able to flush the write queue as well. While the write path doesn't require any updates to serio port drivers as buffered write can be emulated with the existing write() function, the receive path for port drivers must be updated to support the buffered receive. Signed-off-by: Rob Herring --- drivers/input/serio/serio.c | 23 +++++++++++++++++++++++ include/linux/serio.h | 43 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 62 insertions(+), 4 deletions(-) -- 2.9.3 diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 9e8eb7a..c994581 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -989,6 +989,11 @@ int serio_open(struct serio *serio, struct serio_driver *drv) serio_set_drv(serio, NULL); return -1; } + + /* Use buffer receive if the driver provides a callback */ + if (drv->receive_buf) + set_bit(SERIO_MODE_BUFFERED, &drv->flags); + return 0; } EXPORT_SYMBOL(serio_open); @@ -1024,6 +1029,24 @@ irqreturn_t serio_interrupt(struct serio *serio, } EXPORT_SYMBOL(serio_interrupt); +int serio_receive_buf(struct serio *serio, const unsigned char *data, size_t len) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&serio->lock, flags); + + if (likely(serio->drv)) + ret = serio->drv->receive_buf(serio, data, len); + else if (device_is_registered(&serio->dev)) + serio_rescan(serio); + + spin_unlock_irqrestore(&serio->lock, flags); + + return ret; +} +EXPORT_SYMBOL(serio_receive_buf); + struct bus_type serio_bus = { .name = "serio", .drv_groups = serio_driver_groups, diff --git a/include/linux/serio.h b/include/linux/serio.h index c733cff..5d0b69f 100644 --- a/include/linux/serio.h +++ b/include/linux/serio.h @@ -35,6 +35,8 @@ struct serio { spinlock_t lock; int (*write)(struct serio *, unsigned char); + int (*write_buf)(struct serio *, const unsigned char *, size_t); + void (*write_flush)(struct serio *); int (*open)(struct serio *); void (*close)(struct serio *); int (*start)(struct serio *); @@ -69,12 +71,16 @@ struct serio { struct serio_driver { const char *description; + unsigned long flags; + +#define SERIO_MODE_BUFFERED 1 const struct serio_device_id *id_table; bool manual_bind; void (*write_wakeup)(struct serio *); irqreturn_t (*interrupt)(struct serio *, unsigned char, unsigned int); + int (*receive_buf)(struct serio *, const unsigned char *, size_t); int (*connect)(struct serio *, struct serio_driver *drv); int (*reconnect)(struct serio *); void (*disconnect)(struct serio *); @@ -89,6 +95,12 @@ void serio_close(struct serio *serio); void serio_rescan(struct serio *serio); void serio_reconnect(struct serio *serio); irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned int flags); +int serio_receive_buf(struct serio *serio, const unsigned char *data, size_t len); + +static inline bool serio_buffered_mode_enabled(struct serio *serio) +{ + return test_bit(SERIO_MODE_BUFFERED, &serio->drv->flags); +} void __serio_register_port(struct serio *serio, struct module *owner); @@ -121,12 +133,35 @@ void serio_unregister_driver(struct serio_driver *drv); module_driver(__serio_driver, serio_register_driver, \ serio_unregister_driver) +static inline int serio_write_buf(struct serio *serio, const unsigned char *data, size_t len) +{ + int ret; + + if (serio->write_buf) + return serio->write_buf(serio, data, len); + else if (serio->write) { + int i; + for (i = 0; i < len; i++) { + ret = serio->write(serio, data[i]); + if (ret) + break; + } + return i; + } + + return -1; +} + static inline int serio_write(struct serio *serio, unsigned char data) { - if (serio->write) - return serio->write(serio, data); - else - return -1; + int ret = serio_write_buf(serio, &data, 1); + return ret == 1 ? 0 : ret; +} + +static inline void serio_write_flush(struct serio *serio) +{ + if (serio->write_flush) + serio->write_flush(serio); } static inline void serio_drv_write_wakeup(struct serio *serio)