From patchwork Tue Sep 18 11:51:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Simek X-Patchwork-Id: 10604243 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 03E1B15A6 for ; Tue, 18 Sep 2018 11:51:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E7C6B2A7C0 for ; Tue, 18 Sep 2018 11:51:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E5FBD2A802; Tue, 18 Sep 2018 11:51:48 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id BCA002A7C0 for ; Tue, 18 Sep 2018 11:51:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=T0eCp8Jl2YyuRm8GJOE0f3/NciGh7ZSTp19L5KriSwg=; b=F+Fj29wUmjA5PEMgReAItWgHQz +as+RnIUoPY6Wt4jPo6x/lOqEMLiLGqIPNnxapjsaTvPenNcoouXALgJrALBKBBVrHd+qCGDnDdOV TpYfeSX1GZ5nT8c/ux5THKdaEqG6XUzfV04kMCNB14vNGuaFBGE1NySGf7G4hnPqYsW4ZRyJ9zReq 9/9coooSnmthH01PahO074v0DnOOg3322FaZ4oLu8W0zfqeRK/w//96jdCmX2Ym0FyvpFfRQFqdY+ INNYMeWyZYwMXTX8V6NxB8i+M2q4ilN0PNSvQbS1YS56RpK+y2oQQZkMyGFVKSOofhWmn8CzaiZDH mkbmWglA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1g2EXb-0006bG-Rd; Tue, 18 Sep 2018 11:51:39 +0000 Received: from mail-wr1-x442.google.com ([2a00:1450:4864:20::442]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1g2EXY-0006aB-84 for linux-arm-kernel@lists.infradead.org; Tue, 18 Sep 2018 11:51:38 +0000 Received: by mail-wr1-x442.google.com with SMTP id v90-v6so1783126wrc.0 for ; Tue, 18 Sep 2018 04:51:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=monstr-eu.20150623.gappssmtp.com; s=20150623; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=IsEpiKwLKtaKM30im3Lwy5+CeTSbjToZcd6BM396Pos=; b=zHCb64pA3dNYB69QmJZTGx03XLmaZOXDRaea0YPJ6qYu7DfQJVoc5E+IISsQTXAgpE ZCrHbZUhheuYC3dtgynmaxuBCPV5MF2NMvrzs8YuhivpiEr5j43p1PplXFF0TyLNvfJX vHeRgLFGslavEhd3dNmQOFPDdoaYH/qHklHM63bJtnFQ3vOdlIE1e55y5JS+nAIVe7Yn 5z8djZR/eDEyxYH1eZuHYVE2PKt6FcQIal1zJDLkFoDyDUS98vMKVCxXiUzWrTZQylYZ Xd9gXLr28d9NcTXgXmUpxsbSVJdKKei2cJazQJ+MmL6KzKe21+7RJhioA8DKl5orxb5w 3smA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:in-reply-to:references; bh=IsEpiKwLKtaKM30im3Lwy5+CeTSbjToZcd6BM396Pos=; b=lW7BAlrGyZkR+iCjRh5J884St9SgWoi/MM48sY+xx4EmL8WCr565blVt6MXl+2Ywzj IDkfIjHEH2Uu00udjjYCbmdAaYx3lzgb8kiP+vLRbJtLNwamS4HaIGrHCZP7Jn8wrFoe iAVchB+PnvEqEskKiWusoA4bFlSEn7svts0TuuSt62wIiYR2HuK/NFRH5nVAbrGHRTMp FWX3u9W4Rke2m2I93/eXDVVu1FHiyQJqSXUXaBGJT0wQUYaLctKDQ7elycQcHEYmy3qG RJ0xGz7hjCQZJ5l6TBIF71ZbkKnZY43mRlqi4jGSs64dgiaTnGdPHl168p0hXThK7a/+ SLxA== X-Gm-Message-State: APzg51C/u/3Q0Ra9qdlBAKLSsbXP8LleUDOyAElXAiwK8ZMkjRCnNDN1 XRSj81neVC4W11RWm33nFeoRVA== X-Google-Smtp-Source: ANB0VdYwznrnBn1WYynuJ0yk2ncEHsf5JXLmMWa7+OO8qYlzvB5w1s5Zrl2hAU2jKob7gKXvyPl+Bg== X-Received: by 2002:adf:9f13:: with SMTP id l19-v6mr23723307wrf.206.1537271483862; Tue, 18 Sep 2018 04:51:23 -0700 (PDT) Received: from localhost (nat-35.starnet.cz. [178.255.168.35]) by smtp.gmail.com with ESMTPSA id v46-v6sm23261958wrc.63.2018.09.18.04.51.23 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Tue, 18 Sep 2018 04:51:23 -0700 (PDT) From: Michal Simek To: linux-kernel@vger.kernel.org, monstr@monstr.eu Subject: [PATCH v2 2/2] serial: uartps: Change uart ID port allocation Date: Tue, 18 Sep 2018 13:51:20 +0200 Message-Id: X-Mailer: git-send-email 1.9.1 In-Reply-To: <6b07b21f60dcf07e1f6d6e39bae1f3750c4aa804.1537271478.git.michal.simek@xilinx.com> References: <6b07b21f60dcf07e1f6d6e39bae1f3750c4aa804.1537271478.git.michal.simek@xilinx.com> In-Reply-To: <6b07b21f60dcf07e1f6d6e39bae1f3750c4aa804.1537271478.git.michal.simek@xilinx.com> References: <6b07b21f60dcf07e1f6d6e39bae1f3750c4aa804.1537271478.git.michal.simek@xilinx.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180918_045136_311060_CE04B430 X-CRM114-Status: GOOD ( 22.08 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Greg Kroah-Hartman , linux-arm-kernel@lists.infradead.org, linux-serial@vger.kernel.org, Jiri Slaby MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP For IPs which have alias algorightm all the time using that alias and minor number. It means serial20 alias ends up as ttyPS20. If alias is not setup for probed IP instance the first unused position is used but that needs to be checked if it is really empty because another instance doesn't need to be probed at that time. of_alias_get_alias_list() fills alias bitmap which exactly shows which ID is free. If alias pointing to different not compatible IP, it is free to use. cdns_get_id() call is placed below structure allocation to simplify error path. Signed-off-by: Michal Simek --- Changes in v2: - Add handle of return value from of_alias_get_alias_list Needs to be applied on the top of https://lkml.org/lkml/2018/9/3/404 https://lkml.org/lkml/2018/9/3/400 (minor that's why just in case) --- drivers/tty/serial/xilinx_uartps.c | 109 ++++++++++++++++++++++++++++++++----- 1 file changed, 96 insertions(+), 13 deletions(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 71c032744dae..f77200a0f461 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -30,7 +30,6 @@ #define CDNS_UART_TTY_NAME "ttyPS" #define CDNS_UART_NAME "xuartps" #define CDNS_UART_MAJOR 0 /* use dynamic node allocation */ -#define CDNS_UART_NR_PORTS 2 #define CDNS_UART_FIFO_SIZE 64 /* FIFO size */ #define CDNS_UART_REGISTER_SPACE 0x1000 @@ -1370,6 +1369,88 @@ static int __maybe_unused cdns_runtime_resume(struct device *dev) }; MODULE_DEVICE_TABLE(of, cdns_uart_of_match); +/* + * Maximum number of instances without alias IDs but if there is alias + * which target "< MAX_UART_INSTANCES" range this ID can't be used. + */ +#define MAX_UART_INSTANCES 32 + +/* Stores static aliases list */ +static DECLARE_BITMAP(alias_bitmap, MAX_UART_INSTANCES); +static int alias_bitmap_initialized; + +/* Stores actual bitmap of allocated IDs with alias IDs together */ +static DECLARE_BITMAP(bitmap, MAX_UART_INSTANCES); +/* Protect bitmap operations to have unique IDs */ +static DEFINE_MUTEX(bitmap_lock); + +static int cdns_get_id(struct platform_device *pdev) +{ + int id, ret; + + mutex_lock(&bitmap_lock); + + /* Alias list is stable that's why get alias bitmap only once */ + if (!alias_bitmap_initialized) { + ret = of_alias_get_alias_list(cdns_uart_of_match, "serial", + alias_bitmap, MAX_UART_INSTANCES); + if (ret) + return ret; + + alias_bitmap_initialized++; + } + + /* Make sure that alias ID is not taken by instance without alias */ + bitmap_or(bitmap, bitmap, alias_bitmap, MAX_UART_INSTANCES); + + dev_dbg(&pdev->dev, "Alias bitmap: %*pb\n", + MAX_UART_INSTANCES, bitmap); + + /* Look for a serialN alias */ + id = of_alias_get_id(pdev->dev.of_node, "serial"); + if (id < 0) { + dev_warn(&pdev->dev, + "No serial alias passed. Using the first free id\n"); + + /* + * Start with id 0 and check if there is no serial0 alias + * which points to device which is compatible with this driver. + * If alias exists then try next free position. + */ + id = 0; + + for (;;) { + dev_info(&pdev->dev, "Checking id %d\n", id); + id = find_next_zero_bit(bitmap, MAX_UART_INSTANCES, id); + + /* No free empty instance */ + if (id == MAX_UART_INSTANCES) { + dev_err(&pdev->dev, "No free ID\n"); + mutex_unlock(&bitmap_lock); + return -EINVAL; + } + + dev_dbg(&pdev->dev, "The empty id is %d\n", id); + /* Check if ID is empty */ + if (!test_and_set_bit(id, bitmap)) { + /* Break the loop if bit is taken */ + dev_dbg(&pdev->dev, + "Selected ID %d allocation passed\n", + id); + break; + } + dev_dbg(&pdev->dev, + "Selected ID %d allocation failed\n", id); + /* if taking bit fails then try next one */ + id++; + } + } + + mutex_unlock(&bitmap_lock); + + return id; +} + /** * cdns_uart_probe - Platform driver probe * @pdev: Pointer to the platform device structure @@ -1403,21 +1484,17 @@ static int cdns_uart_probe(struct platform_device *pdev) if (!cdns_uart_uart_driver) return -ENOMEM; - /* Look for a serialN alias */ - cdns_uart_data->id = of_alias_get_id(pdev->dev.of_node, "serial"); + cdns_uart_data->id = cdns_get_id(pdev); if (cdns_uart_data->id < 0) - cdns_uart_data->id = 0; - - if (cdns_uart_data->id >= CDNS_UART_NR_PORTS) { - dev_err(&pdev->dev, "Cannot get uart_port structure\n"); - return -ENODEV; - } + return cdns_uart_data->id; /* There is a need to use unique driver name */ driver_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s%d", CDNS_UART_NAME, cdns_uart_data->id); - if (!driver_name) - return -ENOMEM; + if (!driver_name) { + rc = -ENOMEM; + goto err_out_id; + } cdns_uart_uart_driver->owner = THIS_MODULE; cdns_uart_uart_driver->driver_name = driver_name; @@ -1446,7 +1523,7 @@ static int cdns_uart_probe(struct platform_device *pdev) rc = uart_register_driver(cdns_uart_uart_driver); if (rc < 0) { dev_err(&pdev->dev, "Failed to register driver\n"); - return rc; + goto err_out_id; } cdns_uart_data->cdns_uart_driver = cdns_uart_uart_driver; @@ -1587,7 +1664,10 @@ static int cdns_uart_probe(struct platform_device *pdev) clk_disable_unprepare(cdns_uart_data->pclk); err_out_unregister_driver: uart_unregister_driver(cdns_uart_data->cdns_uart_driver); - +err_out_id: + mutex_lock(&bitmap_lock); + clear_bit(cdns_uart_data->id, bitmap); + mutex_unlock(&bitmap_lock); return rc; } @@ -1610,6 +1690,9 @@ static int cdns_uart_remove(struct platform_device *pdev) #endif rc = uart_remove_one_port(cdns_uart_data->cdns_uart_driver, port); port->mapbase = 0; + mutex_lock(&bitmap_lock); + clear_bit(cdns_uart_data->id, bitmap); + mutex_unlock(&bitmap_lock); clk_disable_unprepare(cdns_uart_data->uartclk); clk_disable_unprepare(cdns_uart_data->pclk); pm_runtime_disable(&pdev->dev);