From patchwork Mon Jan 16 22:54:28 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 91588 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp233423qgi; Mon, 16 Jan 2017 14:56:56 -0800 (PST) X-Received: by 10.98.9.78 with SMTP id e75mr39704070pfd.34.1484607415931; Mon, 16 Jan 2017 14:56:55 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 74si15938671pga.139.2017.01.16.14.56.55; Mon, 16 Jan 2017 14:56:55 -0800 (PST) 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 S1751957AbdAPW4s (ORCPT + 25 others); Mon, 16 Jan 2017 17:56:48 -0500 Received: from mail-oi0-f68.google.com ([209.85.218.68]:33970 "EHLO mail-oi0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750970AbdAPWyl (ORCPT ); Mon, 16 Jan 2017 17:54:41 -0500 Received: by mail-oi0-f68.google.com with SMTP id w144so9297984oiw.1; Mon, 16 Jan 2017 14:54:40 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=cdP5a93JMgcNcm5NgLQpe9RZJvVpbMmGqPzJvCC2wn0=; b=iUJLUmZZGsBM5sKVySGfc27gtkcMiMsJimx6NKG840smKJCGOfnZTK2HsNE7mzJTWf v9nIVWk6Co1+AIC59MeXAaT1ddfJBWlHGQlZ4FCabOUSEEdB4cf+hDqhjy710z9BOs8S DCLsMbxSuepyEM9XOOu0QRwAbtlgJYw25ovdI4Eu+n1NCNxU6wW2ST3vSZdRbmw/TTMq s1weqPriTohTpGtW5W9Ez97msTKONJhi282UgN+F2qKbxR2Zy5Nv6zYS1HNV9iao9J2b RhA1OPdfFwjikBZRvSmma8Df/sWnTCEwbTWh/lJvTNzNfNzE5hmn/9RvbYF4Q83hYdpE LiPw== X-Gm-Message-State: AIkVDXIg4d/+kWYs/I56RES4m3dLjMg3Gkhi6EenqfJauPnzO4P0fi8XJifo2gnhRzrNDw== X-Received: by 10.202.175.10 with SMTP id y10mr18267569oie.188.1484607280265; Mon, 16 Jan 2017 14:54:40 -0800 (PST) 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 s125sm11601254oia.0.2017.01.16.14.54.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Jan 2017 14:54:39 -0800 (PST) From: Rob Herring To: Greg Kroah-Hartman , Marcel Holtmann , Jiri Slaby , Sebastian Reichel , Arnd Bergmann , "Dr . H . Nikolaus Schaller" , Peter Hurley , Andy Shevchenko , Alan Cox Cc: Loic Poulain , Pavel Machek , NeilBrown , Linus Walleij , linux-bluetooth@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 1/9] tty: move the non-file related parts of tty_release to new tty_release_struct Date: Mon, 16 Jan 2017 16:54:28 -0600 Message-Id: <20170116225436.17505-2-robh@kernel.org> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20170116225436.17505-1-robh@kernel.org> References: <20170116225436.17505-1-robh@kernel.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org For in-kernel tty users, we need to be able to create and destroy 'struct tty' that are not associated with a file. The creation side is fine, but tty_release() needs to be split into the file handle portion and the struct tty portion. Introduce a new function, tty_release_struct, to handle just the destroying of a struct tty. Signed-off-by: Rob Herring Reviewed-by: Andy Shevchenko Reviewed-By: Sebastian Reichel --- v2: - Add kerneldoc for tty_release_struct drivers/tty/tty_io.c | 50 ++++++++++++++++++++++++++++++++------------------ include/linux/tty.h | 1 + 2 files changed, 33 insertions(+), 18 deletions(-) -- 2.10.1 diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 734a635e7363..4790c0fb5a45 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1745,6 +1745,37 @@ static int tty_release_checks(struct tty_struct *tty, int idx) } /** + * tty_release_struct - release a tty struct + * @tty: tty device + * @idx: index of the tty + * + * Performs the final steps to release and free a tty device. It is + * roughly the reverse of tty_init_dev. + */ +void tty_release_struct(struct tty_struct *tty, int idx) +{ + /* + * Ask the line discipline code to release its structures + */ + tty_ldisc_release(tty); + + /* Wait for pending work before tty destruction commmences */ + tty_flush_works(tty); + + tty_debug_hangup(tty, "freeing structure\n"); + /* + * The release_tty function takes care of the details of clearing + * the slots and preserving the termios structure. The tty_unlock_pair + * should be safe as we keep a kref while the tty is locked (so the + * unlock never unlocks a freed tty). + */ + mutex_lock(&tty_mutex); + release_tty(tty, idx); + mutex_unlock(&tty_mutex); +} +EXPORT_SYMBOL_GPL(tty_release_struct); + +/** * tty_release - vfs callback for close * @inode: inode of tty * @filp: file pointer for handle to tty @@ -1898,25 +1929,8 @@ int tty_release(struct inode *inode, struct file *filp) return 0; tty_debug_hangup(tty, "final close\n"); - /* - * Ask the line discipline code to release its structures - */ - tty_ldisc_release(tty); - - /* Wait for pending work before tty destruction commmences */ - tty_flush_works(tty); - - tty_debug_hangup(tty, "freeing structure\n"); - /* - * The release_tty function takes care of the details of clearing - * the slots and preserving the termios structure. The tty_unlock_pair - * should be safe as we keep a kref while the tty is locked (so the - * unlock never unlocks a freed tty). - */ - mutex_lock(&tty_mutex); - release_tty(tty, idx); - mutex_unlock(&tty_mutex); + tty_release_struct(tty, idx); return 0; } diff --git a/include/linux/tty.h b/include/linux/tty.h index 40144f382516..86c7853282b7 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -528,6 +528,7 @@ extern int tty_alloc_file(struct file *file); extern void tty_add_file(struct tty_struct *tty, struct file *file); extern void tty_free_file(struct file *file); extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx); +extern void tty_release_struct(struct tty_struct *tty, int idx); extern int tty_release(struct inode *inode, struct file *filp); extern void tty_init_termios(struct tty_struct *tty); extern int tty_standard_install(struct tty_driver *driver, From patchwork Mon Jan 16 22:54:29 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 91580 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp232869qgi; Mon, 16 Jan 2017 14:54:53 -0800 (PST) X-Received: by 10.98.1.213 with SMTP id 204mr24866419pfb.61.1484607292969; Mon, 16 Jan 2017 14:54:52 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s1si22865356plj.237.2017.01.16.14.54.52; Mon, 16 Jan 2017 14:54:52 -0800 (PST) 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 S1751573AbdAPWyr (ORCPT + 25 others); Mon, 16 Jan 2017 17:54:47 -0500 Received: from mail-oi0-f68.google.com ([209.85.218.68]:36256 "EHLO mail-oi0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751236AbdAPWym (ORCPT ); Mon, 16 Jan 2017 17:54:42 -0500 Received: by mail-oi0-f68.google.com with SMTP id u143so13623885oif.3; Mon, 16 Jan 2017 14:54:42 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=A69dWcflT18MXaM1bBb0eF909KbgkG67bciihITA4Ks=; b=IdUGidgNDlyHF2YrZe8etP8FviWBj+tIshWb7dQZGjAWwfA1SN8LCn+Q1Hjc9+sA9V QjTlEWVuIQnBmdJJ0S/saMK9bNdaMrwF7YetERKPUyCGjzOuBBpgbkdC0zrguM+GOVQR H9phjD1g7J26386SSue3M0lGCIYxVkXTCq2Iu7kV2zIZhE+cJBAFc2Q+O7F8ehhZiYsI rrAoKHvoB0c6YlqdXBOaqbcyUanVdO1DIxeI+xhpgDsenpJi0QV2VKwVpiqvmldI/ofe CQMpNSX+Z8t9TjjShVGIseAM4N49IXMJhutREpQujCJDw1bX46Gm0IHl5z6SJaZJTt9L YpcQ== X-Gm-Message-State: AIkVDXInAuoU1hWZp9TIQkkjbYG7wKfIcnzpnd7uWbGwXNRYbSo9+YzWC9A57LTCmTi0eA== X-Received: by 10.202.55.70 with SMTP id e67mr18181312oia.51.1484607281576; Mon, 16 Jan 2017 14:54:41 -0800 (PST) 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 s125sm11601254oia.0.2017.01.16.14.54.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Jan 2017 14:54:41 -0800 (PST) From: Rob Herring To: Greg Kroah-Hartman , Marcel Holtmann , Jiri Slaby , Sebastian Reichel , Arnd Bergmann , "Dr . H . Nikolaus Schaller" , Peter Hurley , Andy Shevchenko , Alan Cox Cc: Loic Poulain , Pavel Machek , NeilBrown , Linus Walleij , linux-bluetooth@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, Alan Cox Subject: [PATCH v2 2/9] tty_port: allow a port to be opened with a tty that has no file handle Date: Mon, 16 Jan 2017 16:54:29 -0600 Message-Id: <20170116225436.17505-3-robh@kernel.org> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20170116225436.17505-1-robh@kernel.org> References: <20170116225436.17505-1-robh@kernel.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Alan Cox Let us create tty objects entirely in kernel space. Untested proposal to show why all the ideas around rewriting half the uart stack are not needed. With this a kernel created non file backed tty object could be used to handle data, and set terminal modes. Not all ldiscs can cope with this as N_TTY in particular has to work back to the fs/tty layer. The tty_port code is however otherwise clean of file handles as far as I can tell as is the low level tty port write path used by the ldisc, the configuration low level interfaces and most of the ldiscs. Currently you don't have any exposure to see tty hangups because those are built around the file layer. However a) it's a fixed port so you probably don't care about that b) if you do we can add a callback and c) you almost certainly don't want the userspace tear down/rebuild behaviour anyway. This should however be sufficient if we wanted for example to enumerate all the bluetooth bound fixed ports via ACPI and make them directly available. It doesn't deal with the case of a user opening a port that's also kernel opened and that would need some locking out (so it returned EBUSY if bound to a kernel device of some kind). That needs resolving along with how you "up" or "down" your new bluetooth device, or enumerate it while providing the existing tty API to avoid regressions (and to debug). Alan Reviewed-by: Andy Shevchenko Reviewed-By: Sebastian Reichel --- Alan, Need your SoB here. v2: - no change drivers/tty/tty_io.c | 2 +- drivers/tty/tty_port.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) -- 2.10.1 Signed-off-by: Alan Cox diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 4790c0fb5a45..a1fd3f7d487a 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -855,7 +855,7 @@ static void tty_vhangup_session(struct tty_struct *tty) int tty_hung_up_p(struct file *filp) { - return (filp->f_op == &hung_up_tty_fops); + return (filp && filp->f_op == &hung_up_tty_fops); } EXPORT_SYMBOL(tty_hung_up_p); diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index c3f9d93ba227..606d9e5bf28f 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -335,7 +335,7 @@ EXPORT_SYMBOL(tty_port_lower_dtr_rts); * tty_port_block_til_ready - Waiting logic for tty open * @port: the tty port being opened * @tty: the tty device being bound - * @filp: the file pointer of the opener + * @filp: the file pointer of the opener or NULL * * Implement the core POSIX/SuS tty behaviour when opening a tty device. * Handles: @@ -369,7 +369,7 @@ int tty_port_block_til_ready(struct tty_port *port, tty_port_set_active(port, 1); return 0; } - if (filp->f_flags & O_NONBLOCK) { + if (filp == NULL || (filp->f_flags & O_NONBLOCK)) { /* Indicate we are open */ if (C_BAUD(tty)) tty_port_raise_dtr_rts(port); From patchwork Mon Jan 16 22:54:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 91587 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp233302qgi; Mon, 16 Jan 2017 14:56:29 -0800 (PST) X-Received: by 10.99.146.76 with SMTP id s12mr42515450pgn.8.1484607389580; Mon, 16 Jan 2017 14:56:29 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r6si5488544pli.53.2017.01.16.14.56.29 for ; Mon, 16 Jan 2017 14:56:29 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-bluetooth-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-bluetooth-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-bluetooth-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751412AbdAPW42 (ORCPT ); Mon, 16 Jan 2017 17:56:28 -0500 Received: from mail-oi0-f66.google.com ([209.85.218.66]:36260 "EHLO mail-oi0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751370AbdAPWyn (ORCPT ); Mon, 16 Jan 2017 17:54:43 -0500 Received: by mail-oi0-f66.google.com with SMTP id u143so13623907oif.3; Mon, 16 Jan 2017 14:54:43 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=fJSvvTyMPJa53FibOYBOAAkBpgXZWh83HKahooGYEBo=; b=e/qRjSfONig0qvivA96yftHDj5pheJwtUwkYZrZhoo/pwUZd3l+ai8BoaX2JFnN8xv 1oF6Z9musmOZoNVxyAudvPVR4m4BKW9jC68Y1yxSET81usD/tNRdDIIEIoqbj9mexkbn 1swxIwOjL9ja5PgwMV6uHce+ksqNADPmD1UY9nQ552Uzwc8yUeuHjxcBg05LFe6YvRZX 7gh0iISlmeRsu9+d+/+Dy7BjKfibdLWhSc7h+LBIBAHcTFvxx7ht5ZRKXb4taJjhosEF NihPlzKAz2amqHPo1StXlu3fjmY7k3NmsFguMBWquhd5UyI5mvsT1VupUi7OyOk7s6ia XqaQ== X-Gm-Message-State: AIkVDXJFYM828KWwrl0NueHcREu0WEvHZh3U/kRfRvDpcwq5Z73nBA7mzF99QTBlYn9BMw== X-Received: by 10.202.86.15 with SMTP id k15mr18021857oib.212.1484607282846; Mon, 16 Jan 2017 14:54:42 -0800 (PST) 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 s125sm11601254oia.0.2017.01.16.14.54.41 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Jan 2017 14:54:42 -0800 (PST) From: Rob Herring To: Greg Kroah-Hartman , Marcel Holtmann , Jiri Slaby , Sebastian Reichel , Arnd Bergmann , "Dr . H . Nikolaus Schaller" , Peter Hurley , Andy Shevchenko , Alan Cox Cc: Loic Poulain , Pavel Machek , NeilBrown , Linus Walleij , linux-bluetooth@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 3/9] tty_port: make tty_port_register_device wrap tty_port_register_device_attr Date: Mon, 16 Jan 2017 16:54:30 -0600 Message-Id: <20170116225436.17505-4-robh@kernel.org> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20170116225436.17505-1-robh@kernel.org> References: <20170116225436.17505-1-robh@kernel.org> Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org tty_register_device is just a wrapper for tty_register_device_attr with NULL passed for drvdata and attr_grp. So similarly make tty_port_register_device a wrapper of tty_port_register_device_attr so that additions don't have to be made in both functions. Signed-off-by: Rob Herring Reviewed-by: Andy Shevchenko Reviewed-By: Sebastian Reichel --- v2: - no change drivers/tty/tty_port.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) -- 2.10.1 -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 606d9e5bf28f..1d8804843103 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -67,8 +67,7 @@ struct device *tty_port_register_device(struct tty_port *port, struct tty_driver *driver, unsigned index, struct device *device) { - tty_port_link_device(port, driver, index); - return tty_register_device(driver, index, device); + return tty_port_register_device_attr(port, driver, index, device, NULL, NULL); } EXPORT_SYMBOL_GPL(tty_port_register_device); From patchwork Mon Jan 16 22:54:31 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 91586 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp233292qgi; Mon, 16 Jan 2017 14:56:28 -0800 (PST) X-Received: by 10.84.139.129 with SMTP id 1mr54678167plr.178.1484607388139; Mon, 16 Jan 2017 14:56:28 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r6si5488544pli.53.2017.01.16.14.56.28; Mon, 16 Jan 2017 14:56:28 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-serial-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-serial-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-serial-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751898AbdAPW4L (ORCPT + 2 others); Mon, 16 Jan 2017 17:56:11 -0500 Received: from mail-oi0-f68.google.com ([209.85.218.68]:33298 "EHLO mail-oi0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751412AbdAPWyp (ORCPT ); Mon, 16 Jan 2017 17:54:45 -0500 Received: by mail-oi0-f68.google.com with SMTP id j15so13741394oih.0; Mon, 16 Jan 2017 14:54:44 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=roX02AqYCmg9KSrpfrRZcyKe9tVpLvBFFvpZn904iqk=; b=nA3Qqbwfi+D2ImIVCbXXkrNMX04M+paLI7qEwxjtmUlFMees9bPtuXtdV5wlsWsVmq jpkJuDJdUothkLeaauVIyukQqvrnmUdjl5K2Sr28E9q4ip9LeQXVif3sP5EOfbvAy/6u Qqkih0P+7a3ywxqHqJ5gG6ThpH6uCB728BK1uuFZiBKIt3HTYZ0oNc1Klh4Kt2ShntHy fPkAZ0hlfwIRrf1thlksUC0u3D9qOtoUAvl2huoo6ENvis9sAhvi9PstZVHXcwbH/7b/ pJN0/C4BBroyqkYN7BxjlVnPuRx3LqNRjBFX8p6Rj9IU+4T+h8GG+U89lyZsBRsBOmou UsEA== X-Gm-Message-State: AIkVDXKQy7Sgob0zOmN1Nzdf1pri9DhrZqvBJ87lfSdO41c1RPmpMX6AZifC3S7ONXdV/Q== X-Received: by 10.202.228.70 with SMTP id b67mr17511345oih.173.1484607284256; Mon, 16 Jan 2017 14:54:44 -0800 (PST) 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 s125sm11601254oia.0.2017.01.16.14.54.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Jan 2017 14:54:43 -0800 (PST) From: Rob Herring To: Greg Kroah-Hartman , Marcel Holtmann , Jiri Slaby , Sebastian Reichel , Arnd Bergmann , "Dr . H . Nikolaus Schaller" , Peter Hurley , Andy Shevchenko , Alan Cox Cc: Loic Poulain , Pavel Machek , NeilBrown , Linus Walleij , linux-bluetooth@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 4/9] tty: constify tty_ldisc_receive_buf buffer pointer Date: Mon, 16 Jan 2017 16:54:31 -0600 Message-Id: <20170116225436.17505-5-robh@kernel.org> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20170116225436.17505-1-robh@kernel.org> References: <20170116225436.17505-1-robh@kernel.org> Sender: linux-serial-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org This is needed to work with the client operations which uses const ptrs. Really, the flags pointer could be const, too, but this would be a tree wide fix. Signed-off-by: Rob Herring Reviewed-by: Andy Shevchenko Reviewed-By: Sebastian Reichel --- v2: - no change drivers/tty/tty_buffer.c | 2 +- include/linux/tty.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) -- 2.10.1 -- To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index aa80dc94ddc2..f4dc3e296dd5 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -422,7 +422,7 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string); * * Returns the number of bytes not processed */ -int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p, +int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p, char *f, int count) { if (ld->ops->receive_buf2) diff --git a/include/linux/tty.h b/include/linux/tty.h index 86c7853282b7..21c0fabfed60 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -657,7 +657,7 @@ extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty); extern void tty_ldisc_release(struct tty_struct *tty); extern void tty_ldisc_init(struct tty_struct *tty); extern void tty_ldisc_deinit(struct tty_struct *tty); -extern int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p, +extern int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p, char *f, int count); /* n_tty.c */ From patchwork Mon Jan 16 22:54:32 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 91581 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp232898qgi; Mon, 16 Jan 2017 14:55:01 -0800 (PST) X-Received: by 10.99.139.68 with SMTP id j65mr13663862pge.64.1484607301778; Mon, 16 Jan 2017 14:55:01 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r39si22858693pld.320.2017.01.16.14.55.01 for ; Mon, 16 Jan 2017 14:55:01 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-bluetooth-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-bluetooth-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-bluetooth-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751677AbdAPWyx (ORCPT ); Mon, 16 Jan 2017 17:54:53 -0500 Received: from mail-ot0-f193.google.com ([74.125.82.193]:34080 "EHLO mail-ot0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751481AbdAPWyq (ORCPT ); Mon, 16 Jan 2017 17:54:46 -0500 Received: by mail-ot0-f193.google.com with SMTP id 73so7665720otj.1; Mon, 16 Jan 2017 14:54:46 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=lmlUgGhqUeHugJnEVNCr9dzND+SrOpV8t6xaNmhVRco=; b=KQJfKF6m5b4BDDe7izZom+g5qcZ8AvaaGQWFSmpCQ5fJ1usEbb8U3W+0n4IBKtdt5J oUG97uVXo+qxqryXeMPi9pb35/xFGQZpLQHz8PZJBd2raVVhVo6Ke9fsqXo0MwbvxXNu HBW3hPGgKbYVnKqtmjQdqb1LjeXMSziCMGv973QOzezMPQKR4/UnFgtsuqyZbZA/jPoM 2dqpBlYHSwnBvi8KJU9yyziJZ0ld03A49oAsSkRAAEXggO2K3ZpsbgS15TJ42KN8Qhn2 nHLi+v4SmFTXAPUFs7OeUHvuI6nbCGkyPTxjTidKbeFAnMhwch5GQgF5+qfI+Zj6G8ny AYFA== X-Gm-Message-State: AIkVDXJahj2iP/yBCokjrFpCp6d8Vah50PmZB0k2paylkrc2AMqwGk3RQrpqmdn3n+U84g== X-Received: by 10.157.17.146 with SMTP id v18mr18570355otf.4.1484607285547; Mon, 16 Jan 2017 14:54:45 -0800 (PST) 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 s125sm11601254oia.0.2017.01.16.14.54.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Jan 2017 14:54:45 -0800 (PST) From: Rob Herring To: Greg Kroah-Hartman , Marcel Holtmann , Jiri Slaby , Sebastian Reichel , Arnd Bergmann , "Dr . H . Nikolaus Schaller" , Peter Hurley , Andy Shevchenko , Alan Cox Cc: Loic Poulain , Pavel Machek , NeilBrown , Linus Walleij , linux-bluetooth@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 5/9] tty_port: Add port client functions Date: Mon, 16 Jan 2017 16:54:32 -0600 Message-Id: <20170116225436.17505-6-robh@kernel.org> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20170116225436.17505-1-robh@kernel.org> References: <20170116225436.17505-1-robh@kernel.org> Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Introduce a client (upward direction) operations struct for tty_port clients. Initially supported operations are for receiving data and write wake-up. This will allow for having clients other than an ldisc. Convert the calls to the ldisc to use the client ops as the default operations. Signed-off-by: Rob Herring Reviewed-By: Sebastian Reichel --- v2: - no change drivers/tty/tty_buffer.c | 17 +++-------------- drivers/tty/tty_port.c | 39 ++++++++++++++++++++++++++++++++++++++- include/linux/tty.h | 9 ++++++++- 3 files changed, 49 insertions(+), 16 deletions(-) -- 2.10.1 -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index f4dc3e296dd5..4e7a4e9dcf4d 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -437,7 +437,7 @@ int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p, EXPORT_SYMBOL_GPL(tty_ldisc_receive_buf); static int -receive_buf(struct tty_ldisc *ld, struct tty_buffer *head, int count) +receive_buf(struct tty_port *port, struct tty_buffer *head, int count) { unsigned char *p = char_buf_ptr(head, head->read); char *f = NULL; @@ -445,7 +445,7 @@ receive_buf(struct tty_ldisc *ld, struct tty_buffer *head, int count) if (~head->flags & TTYB_NORMAL) f = flag_buf_ptr(head, head->read); - return tty_ldisc_receive_buf(ld, p, f, count); + return port->client_ops->receive_buf(port, p, f, count); } /** @@ -465,16 +465,6 @@ static void flush_to_ldisc(struct work_struct *work) { struct tty_port *port = container_of(work, struct tty_port, buf.work); struct tty_bufhead *buf = &port->buf; - struct tty_struct *tty; - struct tty_ldisc *disc; - - tty = READ_ONCE(port->itty); - if (tty == NULL) - return; - - disc = tty_ldisc_ref(tty); - if (disc == NULL) - return; mutex_lock(&buf->lock); @@ -504,7 +494,7 @@ static void flush_to_ldisc(struct work_struct *work) continue; } - count = receive_buf(disc, head, count); + count = receive_buf(port, head, count); if (!count) break; head->read += count; @@ -512,7 +502,6 @@ static void flush_to_ldisc(struct work_struct *work) mutex_unlock(&buf->lock); - tty_ldisc_deref(disc); } /** diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 1d8804843103..232a8cbf47bc 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -17,6 +17,41 @@ #include #include +static int tty_port_default_receive_buf(struct tty_port *port, + const unsigned char *p, + const unsigned char *f, size_t count) +{ + int ret; + struct tty_struct *tty; + struct tty_ldisc *disc; + + tty = READ_ONCE(port->itty); + if (!tty) + return 0; + + disc = tty_ldisc_ref(tty); + if (!disc) + return 0; + + ret = tty_ldisc_receive_buf(disc, p, (char *)f, count); + + tty_ldisc_deref(disc); + + return ret; +} + +static void tty_port_default_wakeup(struct tty_port *port) +{ + /* tty_port_tty_wakeup already took a reference to the tty */ + tty_wakeup(port->tty); +} + +static const struct tty_port_client_operations default_client_ops = { + .receive_buf = tty_port_default_receive_buf, + .write_wakeup = tty_port_default_wakeup, +}; + + void tty_port_init(struct tty_port *port) { memset(port, 0, sizeof(*port)); @@ -28,6 +63,7 @@ void tty_port_init(struct tty_port *port) spin_lock_init(&port->lock); port->close_delay = (50 * HZ) / 100; port->closing_wait = (3000 * HZ) / 100; + port->client_ops = &default_client_ops; kref_init(&port->kref); } EXPORT_SYMBOL(tty_port_init); @@ -275,7 +311,8 @@ void tty_port_tty_wakeup(struct tty_port *port) struct tty_struct *tty = tty_port_tty_get(port); if (tty) { - tty_wakeup(tty); + if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) + port->client_ops->write_wakeup(port); tty_kref_put(tty); } } diff --git a/include/linux/tty.h b/include/linux/tty.h index 21c0fabfed60..1017e904c0a3 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -217,12 +217,18 @@ struct tty_port_operations { /* Called on the final put of a port */ void (*destruct)(struct tty_port *port); }; - + +struct tty_port_client_operations { + int (*receive_buf)(struct tty_port *port, const unsigned char *, const unsigned char *, size_t); + void (*write_wakeup)(struct tty_port *port); +}; + struct tty_port { struct tty_bufhead buf; /* Locked internally */ struct tty_struct *tty; /* Back pointer */ struct tty_struct *itty; /* internal back ptr */ const struct tty_port_operations *ops; /* Port operations */ + const struct tty_port_client_operations *client_ops; /* Port client operations */ spinlock_t lock; /* Lock protecting tty field */ int blocked_open; /* Waiting to open */ int count; /* Usage count */ @@ -241,6 +247,7 @@ struct tty_port { based drain is needed else set to size of fifo */ struct kref kref; /* Ref counter */ + void *client_data; }; /* tty_port::iflags bits -- use atomic bit ops */ From patchwork Mon Jan 16 22:54:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 91584 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp233048qgi; Mon, 16 Jan 2017 14:55:35 -0800 (PST) X-Received: by 10.84.232.10 with SMTP id h10mr54023857plk.121.1484607335629; Mon, 16 Jan 2017 14:55:35 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 61si7820515plz.304.2017.01.16.14.55.35; Mon, 16 Jan 2017 14:55:35 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-serial-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-serial-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-serial-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751683AbdAPWyz (ORCPT + 2 others); Mon, 16 Jan 2017 17:54:55 -0500 Received: from mail-ot0-f196.google.com ([74.125.82.196]:34920 "EHLO mail-ot0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751236AbdAPWyr (ORCPT ); Mon, 16 Jan 2017 17:54:47 -0500 Received: by mail-ot0-f196.google.com with SMTP id 65so7671373otq.2; Mon, 16 Jan 2017 14:54:47 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=sp1C0AwDoplLZdsAHww0LhNuDxt+aDElRlur4mDs7jQ=; b=iOzxjTTeyy92JBJHFi7WKUXDLiOwFfveHAxeLrXsm5rCuLopIBobqwH+V5G8GoqPib o5vGYE322zIvgqe45wzOEcdOQvCnKiVn757nB8bZjwi4gScaktyB4ns0RLNU1Z3Zw76R 7oSXJZqZ2pjSebv5kCADoo7mCSsoaLfnPPnJEqcloG6Tmjc6AZfwQ2xTPJSCzlZhPVkD TpjXtzYwE2aQhQIeR7Sv6xWqCtee1fFwjfPOatR5OiaWDgq0nVoZPgN+vwe3k8VDm2r5 9nb98hMDlhtcHfNe8fyrsSprN8Adrk5/aEaQHrXh5WxuPbMDUhbQHS/TnqPwRHOJF4Pg wX7w== X-Gm-Message-State: AIkVDXK++/UyPWhv10mATzjyAlFQ7Gy8GlwSNpQjAf8d2inmoz6UA6dzv52vXVHchNfrzg== X-Received: by 10.157.52.253 with SMTP id t58mr19201213otd.161.1484607286868; Mon, 16 Jan 2017 14:54:46 -0800 (PST) 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 s125sm11601254oia.0.2017.01.16.14.54.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Jan 2017 14:54:46 -0800 (PST) From: Rob Herring To: Greg Kroah-Hartman , Marcel Holtmann , Jiri Slaby , Sebastian Reichel , Arnd Bergmann , "Dr . H . Nikolaus Schaller" , Peter Hurley , Andy Shevchenko , Alan Cox Cc: Loic Poulain , Pavel Machek , NeilBrown , Linus Walleij , linux-bluetooth@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 6/9] dt/bindings: Add a serial/UART attached device binding Date: Mon, 16 Jan 2017 16:54:33 -0600 Message-Id: <20170116225436.17505-7-robh@kernel.org> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20170116225436.17505-1-robh@kernel.org> References: <20170116225436.17505-1-robh@kernel.org> Sender: linux-serial-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org Add a common binding for describing serial/UART attached devices. Common examples are Bluetooth, WiFi, NFC and GPS devices. Serial attached devices are represented as child nodes of a UART node. This may need to be extended for more complex devices with multiple interfaces, but for the simple cases a child node is sufficient. Signed-off-by: Rob Herring --- v2: - Drop reg property - Add max-speed property .../devicetree/bindings/serial/slave-device.txt | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 Documentation/devicetree/bindings/serial/slave-device.txt -- 2.10.1 -- To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/Documentation/devicetree/bindings/serial/slave-device.txt b/Documentation/devicetree/bindings/serial/slave-device.txt new file mode 100644 index 000000000000..f66037928f5f --- /dev/null +++ b/Documentation/devicetree/bindings/serial/slave-device.txt @@ -0,0 +1,36 @@ +Serial Slave Device DT binding + +This documents the binding structure and common properties for serial +attached devices. Common examples include Bluetooth, WiFi, NFC and GPS +devices. + +Serial attached devices shall be a child node of the host UART device the +slave device is attached to. It is expected that the attached device is +the only child node of the UART device. The slave device node name shall +reflect the generic type of device for the node. + +Required Properties: + +- compatible : A string reflecting the vendor and specific device the node + represents. + +Optional Properties: + +- max-speed : The maximum baud rate the device operates at. This should + only be present if the maximum is less than the slave device + can support. For example, a particular board has some signal + quality issue or the host processor can't support higher + baud rates. + +Example: + +serial@1234 { + compatible = "ns16550a"; + interrupts = <1>; + + bluetooth { + compatible = "brcm,bcm43341-bt"; + interrupt-parent = <&gpio>; + interrupts = <10>; + }; +}; From patchwork Mon Jan 16 22:54:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 91585 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp233134qgi; Mon, 16 Jan 2017 14:55:53 -0800 (PST) X-Received: by 10.84.197.1 with SMTP id m1mr34977296pld.123.1484607353806; Mon, 16 Jan 2017 14:55:53 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t85si22846935pfe.160.2017.01.16.14.55.53; Mon, 16 Jan 2017 14:55:53 -0800 (PST) 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 S1751896AbdAPWzv (ORCPT + 25 others); Mon, 16 Jan 2017 17:55:51 -0500 Received: from mail-oi0-f67.google.com ([209.85.218.67]:36274 "EHLO mail-oi0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751585AbdAPWyt (ORCPT ); Mon, 16 Jan 2017 17:54:49 -0500 Received: by mail-oi0-f67.google.com with SMTP id u143so13624017oif.3; Mon, 16 Jan 2017 14:54:49 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=U5S6BWvFfe/3haVYeM8r+oFPJAiduf8IWKWHdxgff1k=; b=Z0oMhmIOrxK7ayviLB6x5Uw861Lih1WQxMh5DvOi2GhAf643d4fw5zyeQ1cFjSqVsM p32qjwMpecar/JFMqEAZIg7tIimcGNdcCm+imr2MeuiGOLiQYTfo3XRV5/ZoLbHeT4BO LflHZngKBJ9If0BCYVqWlQQWlnINuMQM2zx9NlgCD2LuTjllPVA+jNjlPyk13adXu3k7 6qwcf3End9VII4BslDwj/m/iqiNPdoTjqfTzWpEwJmq9sh9fXS61QN51uJ95YBdgw/Jd HFDbPs3W93+lHxE743riSA2E0bYfNahcoM/5ILGApzRsPdaFr9T8kppUZl88P33dnhqv k1Zg== X-Gm-Message-State: AIkVDXISddduvGZWSZo7HuyRXfMtRU3/Hht0tgqR38gzO095NsZCgFTO6eMSOE1SLJ2Lsw== X-Received: by 10.202.86.214 with SMTP id k205mr17814106oib.13.1484607288389; Mon, 16 Jan 2017 14:54:48 -0800 (PST) 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 s125sm11601254oia.0.2017.01.16.14.54.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Jan 2017 14:54:47 -0800 (PST) From: Rob Herring To: Greg Kroah-Hartman , Marcel Holtmann , Jiri Slaby , Sebastian Reichel , Arnd Bergmann , "Dr . H . Nikolaus Schaller" , Peter Hurley , Andy Shevchenko , Alan Cox Cc: Loic Poulain , Pavel Machek , NeilBrown , Linus Walleij , linux-bluetooth@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 7/9] serdev: Introduce new bus for serial attached devices Date: Mon, 16 Jan 2017 16:54:34 -0600 Message-Id: <20170116225436.17505-8-robh@kernel.org> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20170116225436.17505-1-robh@kernel.org> References: <20170116225436.17505-1-robh@kernel.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The serdev bus is designed for devices such as Bluetooth, WiFi, GPS and NFC connected to UARTs on host processors. Tradionally these have been handled with tty line disciplines, rfkill, and userspace glue such as hciattach. This approach has many drawbacks since it doesn't fit into the Linux driver model. Handling of sideband signals, power control and firmware loading are the main issues. This creates a serdev bus with controllers (i.e. host serial ports) and attached devices. Typically, these are point to point connections, but some devices have muxing protocols or a h/w mux is conceivable. Any muxing is not yet supported with the serdev bus. Signed-off-by: Rob Herring Reviewed-By: Sebastian Reichel --- v2: - Change the sysfs visible names to "serial". Kept serdev as kernel internal name. - Make function ptr checks and calls follow a consistent structure - Return error if controller .open() is missing - Sort includes - Add an ACPI TODO note - Fix serdev_controller_add error path handling - Fix DT child device adding error handling - Add modalias sysfs attr and uevent hook - Fix module email address MAINTAINERS | 8 + drivers/char/Kconfig | 1 + drivers/tty/Makefile | 1 + drivers/tty/serdev/Kconfig | 8 + drivers/tty/serdev/Makefile | 3 + drivers/tty/serdev/core.c | 421 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/serdev.h | 213 ++++++++++++++++++++++ 7 files changed, 655 insertions(+) create mode 100644 drivers/tty/serdev/Kconfig create mode 100644 drivers/tty/serdev/Makefile create mode 100644 drivers/tty/serdev/core.c create mode 100644 include/linux/serdev.h -- 2.10.1 diff --git a/MAINTAINERS b/MAINTAINERS index 5f0420a0da5b..dc721d75d2f1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10831,6 +10831,14 @@ S: Maintained F: Documentation/devicetree/bindings/serial/ F: drivers/tty/serial/ +SERIAL DEVICE BUS +M: Rob Herring +L: linux-serial@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/serial/slave-device.txt +F: drivers/tty/serdev/ +F: include/linux/serdev.h + SERIAL IR RECEIVER M: Sean Young L: linux-media@vger.kernel.org diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index fde005ef9d36..db8f74bbaf3e 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -46,6 +46,7 @@ config SGI_MBCS say Y or M here, otherwise say N. source "drivers/tty/serial/Kconfig" +source "drivers/tty/serdev/Kconfig" config TTY_PRINTK tristate "TTY driver to output user messages via printk" diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile index 5817e2397463..b95bed92da9f 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_R3964) += n_r3964.o obj-y += vt/ obj-$(CONFIG_HVC_DRIVER) += hvc/ obj-y += serial/ +obj-$(CONFIG_SERIAL_DEV_BUS) += serdev/ # tty drivers obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o diff --git a/drivers/tty/serdev/Kconfig b/drivers/tty/serdev/Kconfig new file mode 100644 index 000000000000..3b6ecd187bef --- /dev/null +++ b/drivers/tty/serdev/Kconfig @@ -0,0 +1,8 @@ +# +# Serial bus device driver configuration +# +menuconfig SERIAL_DEV_BUS + tristate "Serial device bus" + help + Core support for devices connected via a serial port. + diff --git a/drivers/tty/serdev/Makefile b/drivers/tty/serdev/Makefile new file mode 100644 index 000000000000..01a9b62183f4 --- /dev/null +++ b/drivers/tty/serdev/Makefile @@ -0,0 +1,3 @@ +serdev-objs := core.o + +obj-$(CONFIG_SERIAL_DEV_BUS) += serdev.o diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c new file mode 100644 index 000000000000..a77842ff0217 --- /dev/null +++ b/drivers/tty/serdev/core.c @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2016 Linaro Ltd., Rob Herring + * + * Based on drivers/spmi/spmi.c: + * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static bool is_registered; +static DEFINE_IDA(ctrl_ida); + +static void serdev_device_release(struct device *dev) +{ + struct serdev_device *serdev = to_serdev_device(dev); + kfree(serdev); +} + +static const struct device_type serdev_device_type = { + .release = serdev_device_release, +}; + +static void serdev_ctrl_release(struct device *dev) +{ + struct serdev_controller *ctrl = to_serdev_controller(dev); + ida_simple_remove(&ctrl_ida, ctrl->nr); + kfree(ctrl); +} + +static const struct device_type serdev_ctrl_type = { + .release = serdev_ctrl_release, +}; + +static int serdev_device_match(struct device *dev, struct device_driver *drv) +{ + /* TODO: ACPI and platform matching */ + return of_driver_match_device(dev, drv); +} + +static int serdev_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + /* TODO: ACPI and platform modalias */ + return of_device_uevent_modalias(dev, env); +} + +/** + * serdev_device_add() - add a device previously constructed via serdev_device_alloc() + * @serdev: serdev_device to be added + */ +int serdev_device_add(struct serdev_device *serdev) +{ + struct device *parent = serdev->dev.parent; + int err; + + dev_set_name(&serdev->dev, "%s-%d", dev_name(parent), serdev->nr); + + err = device_add(&serdev->dev); + if (err < 0) { + dev_err(&serdev->dev, "Can't add %s, status %d\n", + dev_name(&serdev->dev), err); + goto err_device_add; + } + + dev_dbg(&serdev->dev, "device %s registered\n", dev_name(&serdev->dev)); + +err_device_add: + return err; +} +EXPORT_SYMBOL_GPL(serdev_device_add); + +/** + * serdev_device_remove(): remove an serdev device + * @serdev: serdev_device to be removed + */ +void serdev_device_remove(struct serdev_device *serdev) +{ + device_unregister(&serdev->dev); +} +EXPORT_SYMBOL_GPL(serdev_device_remove); + +int serdev_device_open(struct serdev_device *serdev) +{ + struct serdev_controller *ctrl = serdev->ctrl; + + if (!ctrl || !ctrl->ops->open) + return -EINVAL; + + return ctrl->ops->open(ctrl); +} +EXPORT_SYMBOL_GPL(serdev_device_open); + +void serdev_device_close(struct serdev_device *serdev) +{ + struct serdev_controller *ctrl = serdev->ctrl; + + if (!ctrl || !ctrl->ops->close) + return; + + ctrl->ops->close(ctrl); +} +EXPORT_SYMBOL_GPL(serdev_device_close); + +int serdev_device_write_buf(struct serdev_device *serdev, + const unsigned char *buf, size_t count) +{ + struct serdev_controller *ctrl = serdev->ctrl; + + if (!ctrl || !ctrl->ops->write_buf) + return -EINVAL; + + return ctrl->ops->write_buf(ctrl, buf, count); +} +EXPORT_SYMBOL_GPL(serdev_device_write_buf); + +void serdev_device_write_flush(struct serdev_device *serdev) +{ + struct serdev_controller *ctrl = serdev->ctrl; + + if (!ctrl || !ctrl->ops->write_flush) + return; + + ctrl->ops->write_flush(ctrl); +} +EXPORT_SYMBOL_GPL(serdev_device_write_flush); + +int serdev_device_write_room(struct serdev_device *serdev) +{ + struct serdev_controller *ctrl = serdev->ctrl; + + if (!ctrl || !ctrl->ops->write_room) + return 0; + + return serdev->ctrl->ops->write_room(ctrl); +} +EXPORT_SYMBOL_GPL(serdev_device_write_room); + +unsigned int serdev_device_set_baudrate(struct serdev_device *serdev, unsigned int speed) +{ + struct serdev_controller *ctrl = serdev->ctrl; + + if (!ctrl || !ctrl->ops->set_baudrate) + return 0; + + return ctrl->ops->set_baudrate(ctrl, speed); + +} +EXPORT_SYMBOL_GPL(serdev_device_set_baudrate); + +void serdev_device_set_flow_control(struct serdev_device *serdev, bool enable) +{ + struct serdev_controller *ctrl = serdev->ctrl; + + if (!ctrl || !ctrl->ops->set_flow_control) + return; + + ctrl->ops->set_flow_control(ctrl, enable); +} +EXPORT_SYMBOL_GPL(serdev_device_set_flow_control); + +static int serdev_drv_probe(struct device *dev) +{ + const struct serdev_device_driver *sdrv = to_serdev_device_driver(dev->driver); + + return sdrv->probe(to_serdev_device(dev)); +} + +static int serdev_drv_remove(struct device *dev) +{ + const struct serdev_device_driver *sdrv = to_serdev_device_driver(dev->driver); + + sdrv->remove(to_serdev_device(dev)); + return 0; +} + +static ssize_t modalias_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2); + buf[len] = '\n'; + buf[len+1] = 0; + return len+1; +} + +static struct device_attribute serdev_device_attrs[] = { + __ATTR_RO(modalias), + __ATTR_NULL +}; + +static struct bus_type serdev_bus_type = { + .name = "serial", + .match = serdev_device_match, + .probe = serdev_drv_probe, + .remove = serdev_drv_remove, + .uevent = serdev_uevent, + .dev_attrs = serdev_device_attrs, +}; + +/** + * serdev_controller_alloc() - Allocate a new serdev device + * @ctrl: associated controller + * + * Caller is responsible for either calling serdev_device_add() to add the + * newly allocated controller, or calling serdev_device_put() to discard it. + */ +struct serdev_device *serdev_device_alloc(struct serdev_controller *ctrl) +{ + struct serdev_device *serdev; + + serdev = kzalloc(sizeof(*serdev), GFP_KERNEL); + if (!serdev) + return NULL; + + serdev->ctrl = ctrl; + ctrl->serdev = serdev; + device_initialize(&serdev->dev); + serdev->dev.parent = &ctrl->dev; + serdev->dev.bus = &serdev_bus_type; + serdev->dev.type = &serdev_device_type; + return serdev; +} +EXPORT_SYMBOL_GPL(serdev_device_alloc); + +/** + * serdev_controller_alloc() - Allocate a new serdev controller + * @parent: parent device + * @size: size of private data + * + * Caller is responsible for either calling serdev_controller_add() to add the + * newly allocated controller, or calling serdev_controller_put() to discard it. + * The allocated private data region may be accessed via + * serdev_controller_get_drvdata() + */ +struct serdev_controller *serdev_controller_alloc(struct device *parent, + size_t size) +{ + struct serdev_controller *ctrl; + int id; + + if (WARN_ON(!parent)) + return NULL; + + ctrl = kzalloc(sizeof(*ctrl) + size, GFP_KERNEL); + if (!ctrl) + return NULL; + + device_initialize(&ctrl->dev); + ctrl->dev.type = &serdev_ctrl_type; + ctrl->dev.bus = &serdev_bus_type; + ctrl->dev.parent = parent; + ctrl->dev.of_node = parent->of_node; + serdev_controller_set_drvdata(ctrl, &ctrl[1]); + + id = ida_simple_get(&ctrl_ida, 0, 0, GFP_KERNEL); + if (id < 0) { + dev_err(parent, + "unable to allocate serdev controller identifier.\n"); + serdev_controller_put(ctrl); + return NULL; + } + + ctrl->nr = id; + dev_set_name(&ctrl->dev, "serial%d", id); + + dev_dbg(&ctrl->dev, "allocated controller 0x%p id %d\n", ctrl, id); + return ctrl; +} +EXPORT_SYMBOL_GPL(serdev_controller_alloc); + +static int of_serdev_register_devices(struct serdev_controller *ctrl) +{ + struct device_node *node; + struct serdev_device *serdev = NULL; + int err; + bool found = false; + + for_each_available_child_of_node(ctrl->dev.of_node, node) { + if (!of_get_property(node, "compatible", NULL)) + continue; + + dev_dbg(&ctrl->dev, "adding child %s\n", node->full_name); + + serdev = serdev_device_alloc(ctrl); + if (!serdev) + continue; + + serdev->dev.of_node = node; + + err = serdev_device_add(serdev); + if (err) { + dev_err(&serdev->dev, + "failure adding device. status %d\n", err); + serdev_device_put(serdev); + } else + found = true; + } + if (!found) + return -ENODEV; + + return 0; +} + +/** + * serdev_controller_add() - Add an serdev controller + * @ctrl: controller to be registered. + * + * Register a controller previously allocated via serdev_controller_alloc() with + * the serdev core. + */ +int serdev_controller_add(struct serdev_controller *ctrl) +{ + int ret; + + /* Can't register until after driver model init */ + if (WARN_ON(!is_registered)) + return -EAGAIN; + + ret = device_add(&ctrl->dev); + if (ret) + return ret; + + ret = of_serdev_register_devices(ctrl); + if (ret) + goto out_dev_del; + + dev_dbg(&ctrl->dev, "serdev%d registered: dev:%p\n", + ctrl->nr, &ctrl->dev); + return 0; + +out_dev_del: + device_del(&ctrl->dev); + return ret; +}; +EXPORT_SYMBOL_GPL(serdev_controller_add); + +/* Remove a device associated with a controller */ +static int serdev_remove_device(struct device *dev, void *data) +{ + struct serdev_device *serdev = to_serdev_device(dev); + if (dev->type == &serdev_device_type) + serdev_device_remove(serdev); + return 0; +} + +/** + * serdev_controller_remove(): remove an serdev controller + * @ctrl: controller to remove + * + * Remove a serdev controller. Caller is responsible for calling + * serdev_controller_put() to discard the allocated controller. + */ +void serdev_controller_remove(struct serdev_controller *ctrl) +{ + int dummy; + + if (!ctrl) + return; + + dummy = device_for_each_child(&ctrl->dev, NULL, + serdev_remove_device); + device_del(&ctrl->dev); +} +EXPORT_SYMBOL_GPL(serdev_controller_remove); + +/** + * serdev_driver_register() - Register client driver with serdev core + * @sdrv: client driver to be associated with client-device. + * + * This API will register the client driver with the serdev framework. + * It is typically called from the driver's module-init function. + */ +int __serdev_device_driver_register(struct serdev_device_driver *sdrv, struct module *owner) +{ + sdrv->driver.bus = &serdev_bus_type; + sdrv->driver.owner = owner; + + /* force drivers to async probe so I/O is possible in probe */ + sdrv->driver.probe_type = PROBE_PREFER_ASYNCHRONOUS; + + return driver_register(&sdrv->driver); +} +EXPORT_SYMBOL_GPL(__serdev_device_driver_register); + +static void __exit serdev_exit(void) +{ + bus_unregister(&serdev_bus_type); +} +module_exit(serdev_exit); + +static int __init serdev_init(void) +{ + int ret; + + ret = bus_register(&serdev_bus_type); + if (ret) + return ret; + + is_registered = true; + return 0; +} +/* Must be before serial drivers register */ +postcore_initcall(serdev_init); + +MODULE_AUTHOR("Rob Herring "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Serial attached device bus"); diff --git a/include/linux/serdev.h b/include/linux/serdev.h new file mode 100644 index 000000000000..6e8cd6ad0a85 --- /dev/null +++ b/include/linux/serdev.h @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2016 Linaro Ltd., Rob Herring + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef _LINUX_SERDEV_H +#define _LINUX_SERDEV_H + +#include +#include + +struct serdev_controller; +struct serdev_device; + +/* + * serdev device functions + */ + +/** + * struct serdev_device_ops - Callback operations for a serdev device + * @receive_buf: Function called with data received from device. + * @write_wakeup: Function called when ready to transmit more data. + */ +struct serdev_device_ops { + int (*receive_buf)(struct serdev_device *, const unsigned char *, size_t); + void (*write_wakeup)(struct serdev_device *); +}; + +/** + * struct serdev_device - Basic representation of an serdev device + * @dev: Driver model representation of the device. + * @nr: Device number on serdev bus. + * @ctrl: serdev controller managing this device. + * @ops: Device operations. + */ +struct serdev_device { + struct device dev; + int nr; + struct serdev_controller *ctrl; + const struct serdev_device_ops *ops; +}; + +static inline struct serdev_device *to_serdev_device(struct device *d) +{ + return container_of(d, struct serdev_device, dev); +} + +static inline void *serdev_device_get_drvdata(const struct serdev_device *serdev) +{ + return dev_get_drvdata(&serdev->dev); +} + +static inline void serdev_device_set_drvdata(struct serdev_device *serdev, void *data) +{ + dev_set_drvdata(&serdev->dev, data); +} + +/** + * serdev_device_put() - decrement serdev device refcount + * @serdev serdev device. + */ +static inline void serdev_device_put(struct serdev_device *serdev) +{ + if (serdev) + put_device(&serdev->dev); +} + +struct serdev_device *serdev_device_alloc(struct serdev_controller *); +int serdev_device_add(struct serdev_device *); +void serdev_device_remove(struct serdev_device *); + +static inline void serdev_device_set_client_ops(struct serdev_device *serdev, + const struct serdev_device_ops *ops) +{ + serdev->ops = ops; +} + +/* + * serdev device driver functions + */ + +/** + * struct serdev_device_driver - serdev slave device driver + * @driver: serdev device drivers should initialize name field of this + * structure. + * @probe: binds this driver to a serdev device. + * @remove: unbinds this driver from the serdev device. + */ +struct serdev_device_driver { + struct device_driver driver; + int (*probe)(struct serdev_device *); + void (*remove)(struct serdev_device *); +}; + +static inline struct serdev_device_driver *to_serdev_device_driver(struct device_driver *d) +{ + return container_of(d, struct serdev_device_driver, driver); +} + +int __serdev_device_driver_register(struct serdev_device_driver *, struct module *); +#define serdev_device_driver_register(sdrv) \ + __serdev_device_driver_register(sdrv, THIS_MODULE) + +/** + * serdev_device_driver_unregister() - unregister an serdev client driver + * @sdrv: the driver to unregister + */ +static inline void serdev_device_driver_unregister(struct serdev_device_driver *sdrv) +{ + if (sdrv) + driver_unregister(&sdrv->driver); +} + +#define module_serdev_device_driver(__serdev_device_driver) \ + module_driver(__serdev_device_driver, serdev_device_driver_register, \ + serdev_device_driver_unregister) + +int serdev_device_open(struct serdev_device *); +void serdev_device_close(struct serdev_device *); +unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int); +void serdev_device_set_flow_control(struct serdev_device *, bool); +int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t); +void serdev_device_write_flush(struct serdev_device *); +int serdev_device_write_room(struct serdev_device *); + +/* + * serdev controller functions + */ +struct serdev_controller_ops { + int (*write_buf)(struct serdev_controller *, const unsigned char *, size_t); + void (*write_flush)(struct serdev_controller *); + int (*write_room)(struct serdev_controller *); + int (*open)(struct serdev_controller *); + void (*close)(struct serdev_controller *); + void (*set_flow_control)(struct serdev_controller *, bool); + unsigned int (*set_baudrate)(struct serdev_controller *, unsigned int); +}; + +/** + * struct serdev_controller - interface to the serdev controller + * @dev: Driver model representation of the device. + * @nr: number identifier for this controller/bus. + * @serdev: Pointer to slave device for this controller. + * @ops: Controller operations. + */ +struct serdev_controller { + struct device dev; + unsigned int nr; + struct serdev_device *serdev; + const struct serdev_controller_ops *ops; +}; + +static inline struct serdev_controller *to_serdev_controller(struct device *d) +{ + return container_of(d, struct serdev_controller, dev); +} + +static inline +void *serdev_controller_get_drvdata(const struct serdev_controller *ctrl) +{ + return ctrl ? dev_get_drvdata(&ctrl->dev) : NULL; +} + +static inline void serdev_controller_set_drvdata(struct serdev_controller *ctrl, + void *data) +{ + dev_set_drvdata(&ctrl->dev, data); +} + +/** + * serdev_controller_put() - decrement controller refcount + * @ctrl serdev controller. + */ +static inline void serdev_controller_put(struct serdev_controller *ctrl) +{ + if (ctrl) + put_device(&ctrl->dev); +} + +struct serdev_controller *serdev_controller_alloc(struct device *, size_t); +int serdev_controller_add(struct serdev_controller *); +void serdev_controller_remove(struct serdev_controller *); + +static inline void serdev_controller_write_wakeup(struct serdev_controller *ctrl) +{ + struct serdev_device *serdev = ctrl->serdev; + + if (!serdev || !serdev->ops->write_wakeup) + return; + + serdev->ops->write_wakeup(ctrl->serdev); +} + +static inline int serdev_controller_receive_buf(struct serdev_controller *ctrl, + const unsigned char *data, + size_t count) +{ + struct serdev_device *serdev = ctrl->serdev; + + if (!serdev || !serdev->ops->receive_buf) + return -EINVAL; + + return serdev->ops->receive_buf(ctrl->serdev, data, count); +} + +#endif /*_LINUX_SERDEV_H */ From patchwork Mon Jan 16 22:54:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 91582 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp232903qgi; Mon, 16 Jan 2017 14:55:02 -0800 (PST) X-Received: by 10.84.217.216 with SMTP id d24mr53877660plj.101.1484607302572; Mon, 16 Jan 2017 14:55:02 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r39si22858693pld.320.2017.01.16.14.55.02; Mon, 16 Jan 2017 14:55:02 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-serial-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-serial-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-serial-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751729AbdAPWy6 (ORCPT + 2 others); Mon, 16 Jan 2017 17:54:58 -0500 Received: from mail-oi0-f68.google.com ([209.85.218.68]:33995 "EHLO mail-oi0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751594AbdAPWyu (ORCPT ); Mon, 16 Jan 2017 17:54:50 -0500 Received: by mail-oi0-f68.google.com with SMTP id w144so9298193oiw.1; Mon, 16 Jan 2017 14:54:50 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=a8xbr/KeMvynPUu7iEQVnWGgcKnJLYpM72lTt7COSWE=; b=jupICZm/DtxMFys6g5zbVVkWfHxWuie/dzgJmFF6ijm/gjNTV20PMDbQ/sSNYz6M+c +QLm48sfjQDl+JCkGaRoi7stcZwKeouVd3GK9xKVnV8+MBeNmhw+SF+2truU3qQa7AzG Il9c2s2YQ23YB0NGRAdJmlvya7dn4Dd8ByM7A7WibZ6rxY9VfGvh0D9qXDqb/Jpqpj9q /bSYtp+Y2mQMtVhOXJGjmAp8YM1EstSgfFxsv9PmWpfkraanx3E676rHCu3iRNkuQqWH 1R0uoCYqAsjxc4zW7TCktsw0qEDd3GY6hEvql6mthjUTxUkMfvCKPdmzsTmIJbjlbJlm mhDg== X-Gm-Message-State: AIkVDXLWO25BDQ/baz5gRjYuD5vxJDytuXZFUr183zTn+spL7Kh1m+jzmCb1yKF8/3RyHA== X-Received: by 10.202.222.11 with SMTP id v11mr18112899oig.194.1484607289650; Mon, 16 Jan 2017 14:54:49 -0800 (PST) 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 s125sm11601254oia.0.2017.01.16.14.54.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Jan 2017 14:54:49 -0800 (PST) From: Rob Herring To: Greg Kroah-Hartman , Marcel Holtmann , Jiri Slaby , Sebastian Reichel , Arnd Bergmann , "Dr . H . Nikolaus Schaller" , Peter Hurley , Andy Shevchenko , Alan Cox Cc: Loic Poulain , Pavel Machek , NeilBrown , Linus Walleij , linux-bluetooth@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 8/9] serdev: add a tty port controller driver Date: Mon, 16 Jan 2017 16:54:35 -0600 Message-Id: <20170116225436.17505-9-robh@kernel.org> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20170116225436.17505-1-robh@kernel.org> References: <20170116225436.17505-1-robh@kernel.org> Sender: linux-serial-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org Add a serdev controller driver for tty ports. The controller is registered with serdev when tty ports are registered with the TTY core. As the TTY core is built-in only, this has the side effect of making serdev built-in as well. Signed-off-by: Rob Herring Reviewed-By: Sebastian Reichel --- v2: - Sort includes - Made goto labels more descriptive - Use tty-> instead of serdev->tty-> where possible - Drop DT specific check in serdev_tty_port_register. DT specifics are only in core bus code now. - Comments on #endif's - Use "depends on SERIAL_DEV_BUS != m" instead of "= y" - Dropped module properties (not a module) drivers/tty/serdev/Kconfig | 8 ++ drivers/tty/serdev/Makefile | 2 + drivers/tty/serdev/serdev-ttyport.c | 240 ++++++++++++++++++++++++++++++++++++ include/linux/serdev.h | 21 ++++ 4 files changed, 271 insertions(+) create mode 100644 drivers/tty/serdev/serdev-ttyport.c -- 2.10.1 -- To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/tty/serdev/Kconfig b/drivers/tty/serdev/Kconfig index 3b6ecd187bef..cdc6b820cf93 100644 --- a/drivers/tty/serdev/Kconfig +++ b/drivers/tty/serdev/Kconfig @@ -6,3 +6,11 @@ menuconfig SERIAL_DEV_BUS help Core support for devices connected via a serial port. +if SERIAL_DEV_BUS + +config SERIAL_DEV_CTRL_TTYPORT + bool "Serial device TTY port controller" + depends on TTY + depends on SERIAL_DEV_BUS != m + +endif diff --git a/drivers/tty/serdev/Makefile b/drivers/tty/serdev/Makefile index 01a9b62183f4..0cbdb9444d9d 100644 --- a/drivers/tty/serdev/Makefile +++ b/drivers/tty/serdev/Makefile @@ -1,3 +1,5 @@ serdev-objs := core.o obj-$(CONFIG_SERIAL_DEV_BUS) += serdev.o + +obj-$(CONFIG_SERIAL_DEV_CTRL_TTYPORT) += serdev-ttyport.o diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c new file mode 100644 index 000000000000..bdd2db7db273 --- /dev/null +++ b/drivers/tty/serdev/serdev-ttyport.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2016 Linaro Ltd., Rob Herring + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include + +#define SERPORT_BUSY 1 +#define SERPORT_ACTIVE 2 +#define SERPORT_DEAD 3 + +struct serport { + struct tty_port *port; + struct tty_struct *tty; + struct tty_driver *tty_drv; + int tty_idx; + struct mutex lock; + unsigned long flags; +}; + +/* + * Callback functions from the tty port. + */ + +static int ttyport_receive_buf(struct tty_port *port, const unsigned char *cp, + const unsigned char *fp, size_t count) +{ + struct serdev_controller *ctrl = port->client_data; + struct serport *serport = serdev_controller_get_drvdata(ctrl); + + mutex_lock(&serport->lock); + + if (!test_bit(SERPORT_ACTIVE, &serport->flags)) + goto out_unlock; + + serdev_controller_receive_buf(ctrl, cp, count); + +out_unlock: + mutex_unlock(&serport->lock); + return count; +} + +static void ttyport_write_wakeup(struct tty_port *port) +{ + struct serdev_controller *ctrl = port->client_data; + struct serport *serport = serdev_controller_get_drvdata(ctrl); + + clear_bit(TTY_DO_WRITE_WAKEUP, &port->tty->flags); + + if (test_bit(SERPORT_ACTIVE, &serport->flags)) + serdev_controller_write_wakeup(ctrl); +} + +static const struct tty_port_client_operations client_ops = { + .receive_buf = ttyport_receive_buf, + .write_wakeup = ttyport_write_wakeup, +}; + +/* + * Callback functions from the serdev core. + */ + +static int ttyport_write_buf(struct serdev_controller *ctrl, const unsigned char *data, size_t len) +{ + struct serport *serport = serdev_controller_get_drvdata(ctrl); + struct tty_struct *tty = serport->tty; + + set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + return tty->ops->write(serport->tty, data, len); +} + +static void ttyport_write_flush(struct serdev_controller *ctrl) +{ + struct serport *serport = serdev_controller_get_drvdata(ctrl); + struct tty_struct *tty = serport->tty; + + tty_driver_flush_buffer(tty); +} + +static int ttyport_write_room(struct serdev_controller *ctrl) +{ + struct serport *serport = serdev_controller_get_drvdata(ctrl); + struct tty_struct *tty = serport->tty; + + return tty_write_room(tty); +} + + +static int ttyport_open(struct serdev_controller *ctrl) +{ + struct serport *serport = serdev_controller_get_drvdata(ctrl); + struct tty_struct *tty; + struct ktermios ktermios; + + tty = tty_init_dev(serport->tty_drv, serport->tty_idx); + serport->tty = tty; + + serport->port->client_ops = &client_ops; + serport->port->client_data = ctrl; + + tty->receive_room = 65536; + + if (tty->ops->open) + tty->ops->open(serport->tty, NULL); + else + tty_port_open(serport->port, tty, NULL); + + /* Bring the UART into a known 8 bits no parity hw fc state */ + ktermios = tty->termios; + ktermios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | + INLCR | IGNCR | ICRNL | IXON); + ktermios.c_oflag &= ~OPOST; + ktermios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + ktermios.c_cflag &= ~(CSIZE | PARENB); + ktermios.c_cflag |= CS8; + ktermios.c_cflag |= CRTSCTS; + tty_set_termios(tty, &ktermios); + + set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + + mutex_lock(&serport->lock); + set_bit(SERPORT_ACTIVE, &serport->flags); + mutex_unlock(&serport->lock); + + tty_unlock(serport->tty); + return 0; +} + +static void ttyport_close(struct serdev_controller *ctrl) +{ + struct serport *serport = serdev_controller_get_drvdata(ctrl); + struct tty_struct *tty = serport->tty; + + mutex_lock(&serport->lock); + + if (tty->ops->close) + tty->ops->close(tty, NULL); + + tty_release_struct(tty, serport->tty_idx); + + clear_bit(SERPORT_ACTIVE, &serport->flags); + mutex_unlock(&serport->lock); +} + +static unsigned int ttyport_set_baudrate(struct serdev_controller *ctrl, unsigned int speed) +{ + struct serport *serport = serdev_controller_get_drvdata(ctrl); + struct tty_struct *tty = serport->tty; + struct ktermios ktermios = tty->termios; + + ktermios.c_cflag &= ~CBAUD; + tty_termios_encode_baud_rate(&ktermios, speed, speed); + + /* tty_set_termios() return not checked as it is always 0 */ + tty_set_termios(tty, &ktermios); + return speed; +} + +static void ttyport_set_flow_control(struct serdev_controller *ctrl, bool enable) +{ + struct serport *serport = serdev_controller_get_drvdata(ctrl); + struct tty_struct *tty = serport->tty; + struct ktermios ktermios = tty->termios; + + if (enable) + ktermios.c_cflag |= CRTSCTS; + else + ktermios.c_cflag &= ~CRTSCTS; + + tty_set_termios(tty, &ktermios); +} + +struct serdev_controller_ops ctrl_ops = { + .write_buf = ttyport_write_buf, + .write_flush = ttyport_write_flush, + .write_room = ttyport_write_room, + .open = ttyport_open, + .close = ttyport_close, + .set_flow_control = ttyport_set_flow_control, + .set_baudrate = ttyport_set_baudrate, +}; + +struct device *serdev_tty_port_register(struct tty_port *port, + struct device *parent, + struct tty_driver *drv, int idx) +{ + struct serdev_controller *ctrl; + struct serport *serport; + int ret; + + if (!port || !drv || !parent) + return ERR_PTR(-ENODEV); + + ctrl = serdev_controller_alloc(parent, sizeof(struct serport)); + if (!ctrl) + return ERR_PTR(-ENOMEM); + serport = serdev_controller_get_drvdata(ctrl); + + mutex_init(&serport->lock); + serport->port = port; + serport->tty_idx = idx; + serport->tty_drv = drv; + + ctrl->ops = &ctrl_ops; + + ret = serdev_controller_add(ctrl); + if (ret) + goto err_controller_put; + + dev_info(&ctrl->dev, "tty port %s%d registered\n", drv->name, idx); + return &ctrl->dev; + +err_controller_put: + serdev_controller_put(ctrl); + return ERR_PTR(ret); +} + +void serdev_tty_port_unregister(struct tty_port *port) +{ + struct serdev_controller *ctrl = port->client_data; + struct serport *serport = serdev_controller_get_drvdata(ctrl); + + if (!serport) + return; + + serdev_controller_remove(ctrl); + port->client_ops = NULL; + port->client_data = NULL; + serdev_controller_put(ctrl); +} diff --git a/include/linux/serdev.h b/include/linux/serdev.h index 6e8cd6ad0a85..fe7becd881aa 100644 --- a/include/linux/serdev.h +++ b/include/linux/serdev.h @@ -210,4 +210,25 @@ static inline int serdev_controller_receive_buf(struct serdev_controller *ctrl, return serdev->ops->receive_buf(ctrl->serdev, data, count); } +/* + * serdev hooks into TTY core + */ +struct tty_port; +struct tty_driver; + +#ifdef CONFIG_SERIAL_DEV_CTRL_TTYPORT +struct device *serdev_tty_port_register(struct tty_port *port, + struct device *parent, + struct tty_driver *drv, int idx); +void serdev_tty_port_unregister(struct tty_port *port); +#else +static inline struct device *serdev_tty_port_register(struct tty_port *port, + struct device *parent, + struct tty_driver *drv, int idx) +{ + return ERR_PTR(-ENODEV); +} +static inline void serdev_tty_port_unregister(struct tty_port *port) {} +#endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */ + #endif /*_LINUX_SERDEV_H */ From patchwork Mon Jan 16 22:54:36 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 91583 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp232949qgi; Mon, 16 Jan 2017 14:55:13 -0800 (PST) X-Received: by 10.84.233.193 with SMTP id m1mr53863231pln.126.1484607313067; Mon, 16 Jan 2017 14:55:13 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 61si7820515plz.304.2017.01.16.14.55.12; Mon, 16 Jan 2017 14:55:13 -0800 (PST) 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 S1751799AbdAPWzC (ORCPT + 25 others); Mon, 16 Jan 2017 17:55:02 -0500 Received: from mail-ot0-f193.google.com ([74.125.82.193]:36728 "EHLO mail-ot0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751632AbdAPWyv (ORCPT ); Mon, 16 Jan 2017 17:54:51 -0500 Received: by mail-ot0-f193.google.com with SMTP id 36so7677357otx.3; Mon, 16 Jan 2017 14:54:51 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=OqZulPUYAji3YtVEAd8dQZW73u4+iZl3Qjp6XNO2Bi0=; b=Ldq95xHPfvhEeiYdnXfjOfUehbbzJlxyLkew598NdkQp+5ETq37MNXAVGA7qzGoHZA fce08yfWOIqk6k2nIbBvfsDzAEFpQUz0ZrrkfwpD+Y6opEcSns4uY0Vzxk1rV4pqbSy5 18+uRDPTjvgqmcd/htRqCR2+3XR3lvpz6KD/OEFkJkR3Ey2wa077zv6HU7BGwlPW+xle SGV15TfMiodkkMKxH1T+2wsU1YtaJrrWXqGYl+Br4vHGW+GuR6faPOThtOZ0K+ukr9ou O75REqUf9raBkepC2rcK6IE0rOwSXvSl2AuOv+Dau9/4sy3lZTB0iAI0OoIHQ8Ab9QTt wB0A== X-Gm-Message-State: AIkVDXKre77GmH+OpR4aJcytsJ7mL6Kpwwrp/GAGDpJIJUs/zBrB2xsFlgE5uMzW44o/+g== X-Received: by 10.157.56.138 with SMTP id p10mr19012612otc.195.1484607290936; Mon, 16 Jan 2017 14:54:50 -0800 (PST) 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 s125sm11601254oia.0.2017.01.16.14.54.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Jan 2017 14:54:50 -0800 (PST) From: Rob Herring To: Greg Kroah-Hartman , Marcel Holtmann , Jiri Slaby , Sebastian Reichel , Arnd Bergmann , "Dr . H . Nikolaus Schaller" , Peter Hurley , Andy Shevchenko , Alan Cox Cc: Loic Poulain , Pavel Machek , NeilBrown , Linus Walleij , linux-bluetooth@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 9/9] tty_port: register tty ports with serdev bus Date: Mon, 16 Jan 2017 16:54:36 -0600 Message-Id: <20170116225436.17505-10-robh@kernel.org> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20170116225436.17505-1-robh@kernel.org> References: <20170116225436.17505-1-robh@kernel.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Register a serdev controller with the serdev bus when a tty_port is registered. This creates the serdev controller and create's serdev devices for any DT child nodes of the tty_port's parent (i.e. the UART device). Signed-off-by: Rob Herring Reviewed-By: Sebastian Reichel --- v2: - Skip creating the tty device file node when serdev_tty_port_register finds slave devices. drivers/tty/tty_port.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) -- 2.10.1 diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 232a8cbf47bc..d7e0dced967b 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -16,6 +16,7 @@ #include #include #include +#include static int tty_port_default_receive_buf(struct tty_port *port, const unsigned char *p, @@ -125,7 +126,15 @@ struct device *tty_port_register_device_attr(struct tty_port *port, struct device *device, void *drvdata, const struct attribute_group **attr_grp) { + struct device *dev; + tty_port_link_device(port, driver, index); + + dev = serdev_tty_port_register(port, device, driver, index); + if (PTR_ERR(dev) != -ENODEV) + /* Skip creating cdev if we registered a serdev device */ + return dev; + return tty_register_device_attr(driver, index, device, drvdata, attr_grp); } @@ -177,6 +186,9 @@ static void tty_port_destructor(struct kref *kref) /* check if last port ref was dropped before tty release */ if (WARN_ON(port->itty)) return; + + serdev_tty_port_unregister(port); + if (port->xmit_buf) free_page((unsigned long)port->xmit_buf); tty_port_destroy(port);