From patchwork Thu Apr 20 12:03:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sjoerd Simons X-Patchwork-Id: 97768 Delivered-To: patch@linaro.org Received: by 10.140.109.52 with SMTP id k49csp762375qgf; Thu, 20 Apr 2017 05:04:05 -0700 (PDT) X-Received: by 10.98.34.212 with SMTP id p81mr7896645pfj.118.1492689845649; Thu, 20 Apr 2017 05:04:05 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o5si6227689pgk.339.2017.04.20.05.04.05; Thu, 20 Apr 2017 05:04:05 -0700 (PDT) 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=collabora.co.uk Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S944568AbdDTMEE (ORCPT + 3 others); Thu, 20 Apr 2017 08:04:04 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:33751 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S943652AbdDTMEE (ORCPT ); Thu, 20 Apr 2017 08:04:04 -0400 Received: from dawn.luon.net (unknown [IPv6:2001:1af8:fe00:8421:84eb:4143:10ee:73da]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: sjoerd) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id BEB34260E1B; Thu, 20 Apr 2017 13:04:01 +0100 (BST) Received: by dawn.luon.net (Postfix, from userid 1000) id EC74B2FA2D6F; Thu, 20 Apr 2017 14:03:57 +0200 (CEST) From: Sjoerd Simons To: Greg Kroah-Hartman , linux-serial@vger.kernel.org Cc: Geert Uytterhoeven , linux-kernel@vger.kernel.org, Jiri Slaby Subject: [PATCH] RFC: serial: core: Dynamic minor support Date: Thu, 20 Apr 2017 14:03:57 +0200 Message-Id: <20170420120357.18317-1-sjoerd.simons@collabora.co.uk> X-Mailer: git-send-email 2.11.0 Sender: linux-serial-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org Quite a few serial port drivers use the "Low-density serial ports" major which is rather packed. And ofcourse as time passes, things get slightly less dense. For example the SCI serial port driver has an allocation of 4 minors, but in reality it supports up to 11 ports these days. Causing it to overlap with the allocations for the AMBA PL010 serial port and firmware console. While some other drivers are simply using minor regions never allocated to them (both samsung and AMBA PL011 serial user minor 64 and onwards while those are allocated to the Altix serial card driver). Cleary this doesn't scale. Furthermore some other drivers rely upon the usage of a dynamic major e.g. the tegra serial port driver. However as there is only a block of 20 major numbers reserved for dynamic assignment that isn't going to scale either for multiplatform kernels (I can already easily build 18 different serial drivers on an arm64 kernel today). This patch tries to address the issue adding a new to configuration option which will let all serial ports use the "Low-density serial ports" major and dynamically allocate minor ranges out of that rather then using the driver defined areas. Given there are 20 bits worth of minors available this should be enough for everyone... This option is not enabled by default (for now) to not break setups with a static /dev. This does not try to address device naming by making all serial ports be ttyS as that would first need a better way of deterministically specifying serial console devices. While it would be an option to move to consistent serial device naming while keeping the current console names, having both not aligned would probably confuse everyone massively. Signed-off-by: Sjoerd Simons --- drivers/tty/serial/Kconfig | 10 ++++++++++ drivers/tty/serial/serial_core.c | 38 ++++++++++++++++++++++++++++++++++++++ include/linux/serial_core.h | 6 ++++++ 3 files changed, 54 insertions(+) -- 2.11.0 -- 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/serial/Kconfig b/drivers/tty/serial/Kconfig index 6117ac8da48f..65a7261f3060 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -7,6 +7,16 @@ if TTY menu "Serial drivers" depends on HAS_IOMEM +config SERIAL_DYNAMIC_MINORS + bool "Dynamic serial minors allocation" + help + If you say Y here the serial subsystem will use dynamic minors for all + serial devices, using the Low density serial port major. Note that + this requires the system to a non-static /dev to support a getty on + serial console. + + If you are unsure about this, say N here. + config SERIAL_EARLYCON bool help diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 3fe56894974a..37014c70dd69 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -44,6 +44,32 @@ */ static DEFINE_MUTEX(port_mutex); +#ifdef CONFIG_SERIAL_DYNAMIC_MINORS +/* List of uarts to allow for allocation of dynamic minor ranges*/ +LIST_HEAD(dynamic_uarts); +DEFINE_MUTEX(dynamic_uarts_mutex); + +static void +uart_setup_major_minor(struct uart_driver *drv) +{ + int start = 0; + struct uart_driver *d; + + drv->major = LOW_DENSITY_UART_MAJOR; + mutex_lock(&dynamic_uarts_mutex); + + list_for_each_entry(d, &dynamic_uarts, dynamic_uarts) { + if (start + drv->nr < d->minor) + break; + start = d->minor + d->nr; + } + list_add_tail(&drv->dynamic_uarts, &d->dynamic_uarts); + drv->minor = start; + + mutex_unlock(&dynamic_uarts_mutex); +} +#endif + /* * lockdep: port->lock is initialized in two places, but we * want only one lock-class: @@ -2458,6 +2484,11 @@ int uart_register_driver(struct uart_driver *drv) BUG_ON(drv->state); +#ifdef CONFIG_SERIAL_DYNAMIC_MINORS + INIT_LIST_HEAD(&drv->dynamic_uarts); + uart_setup_major_minor(drv); +#endif + /* * Maybe we should be using a slab cache for this, especially if * we have a large number of ports to handle. @@ -2527,6 +2558,13 @@ void uart_unregister_driver(struct uart_driver *drv) put_tty_driver(p); for (i = 0; i < drv->nr; i++) tty_port_destroy(&drv->state[i].port); + +#ifdef CONFIG_SERIAL_DYNAMIC_MINORS + mutex_lock(&dynamic_uarts_mutex); + list_del(&drv->dynamic_uarts); + mutex_unlock(&dynamic_uarts_mutex); +#endif + kfree(drv->state); drv->state = NULL; drv->tty_driver = NULL; diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 58484fb35cc8..890bbefb3f90 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -31,6 +31,8 @@ #include #include +#define LOW_DENSITY_UART_MAJOR 204 + #ifdef CONFIG_SERIAL_CORE_CONSOLE #define uart_console(port) \ ((port)->cons && (port)->cons->index == (port)->line) @@ -313,6 +315,10 @@ struct uart_driver { */ struct uart_state *state; struct tty_driver *tty_driver; + +#ifdef CONFIG_SERIAL_DYNAMIC_MINORS + struct list_head dynamic_uarts; +#endif }; void uart_write_wakeup(struct uart_port *port);