Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp1658234imm; Mon, 3 Sep 2018 06:16:21 -0700 (PDT) X-Google-Smtp-Source: ANB0Vdb3uJC9367hK9llBl2jKpEE25hzkypy3P7TglWjAsQUMF0M1lGku3e6MFq5nOlC4Hn1wfNY X-Received: by 2002:a62:2483:: with SMTP id k3-v6mr29761196pfk.195.1535980581692; Mon, 03 Sep 2018 06:16:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1535980581; cv=none; d=google.com; s=arc-20160816; b=SEbrAYPwH26clvRbvOG2W2Au874AfmCWkpQrhRfdxEcEQCivcD7oDhlRIun3Fl4Ora EF7OqrwUHvoOQ7u1sIftqFdcyW3LmyPiSsi7b3Q47C/ZdBidfYav5aln37ajPHZ0BCL1 GUD0SWtldPSms2XfUA9xDZaKZyiLKz37CS08tkkhWQFLDioZqi3JG0cq9drraIkWiAGT lCAzT7mp25uxjuskydqucup3JJ238gDIXjcMNMGfYRsrd3kYGMru+XcUBqFHFk1Pm1eF ecHprYvd0XA9Pkd3KFkuXq4e+Emiu9BFpiQPbepYHvK14I20lSGP+jKZ39IzG+EjwMt7 iMtg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=4kS78oXJZUGrKCzUZpGpGSSBJzhOYunPNUj2kwOzEgs=; b=MwNwZBmZ78qEmIQXjHwo3vJYf0ZW8QqJWium2X5CMabtbbTpxoCmB3a+xuQQofz/Qw cMFX9QisX9TxrBoM6aCE3jQEF9VHouXzofERGTbefIxOs7JqTtBIrV/6hsEzWtmz+DSd KW1Rzoy456tiqjn3JFu7IbJ3+L10/tule6i4Oj8+3Ywj7r1/LiRw6yDR6z4bx4u17T1b bpEGgF1uiTPQlvq+PxfCmu9n9IaWw9rGvXQrCQSRAs3Qc4LTovDvhO33uThJussKi0ez sqIaWGfQ+EumR9Wt8p6q8pRfEfT1r1P6m68mTnbW43mROREWld7OkvemcnOKpNQ71lh8 cdKg== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@monstr-eu.20150623.gappssmtp.com header.s=20150623 header.b=xHp9iAw+; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r14-v6si14022081pli.447.2018.09.03.06.16.06; Mon, 03 Sep 2018 06:16:21 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=fail header.i=@monstr-eu.20150623.gappssmtp.com header.s=20150623 header.b=xHp9iAw+; 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 S1727796AbeICRen (ORCPT + 99 others); Mon, 3 Sep 2018 13:34:43 -0400 Received: from mail-wm0-f66.google.com ([74.125.82.66]:38559 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727528AbeICRem (ORCPT ); Mon, 3 Sep 2018 13:34:42 -0400 Received: by mail-wm0-f66.google.com with SMTP id t25-v6so1109505wmi.3 for ; Mon, 03 Sep 2018 06:14:35 -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=4kS78oXJZUGrKCzUZpGpGSSBJzhOYunPNUj2kwOzEgs=; b=xHp9iAw+8VrtJ55yCGbUS/LsbIfQx11KWhD3nKNJpUdBQuS0Akxlsq2/Ar5zhzBh2B +Z4+giTfRKlN8XnLLp5NLAQaAWOPqwms9VzNbVcmTihl8TpEtlexlj4Ifn0+HzIaKnnp PxHnSlaT95qkLYtFRgsnb+/h4gCCuQDQy6wA88c8m4LajBk5MoMmD0ahlvFudLR8/Th5 f5O8hJgVl65Kug+gXw5XfVxJOiez6nQbfCX7XRiv327okvPnFeLWwI3NGvPTV9W1mxWg kycv/bZG3jqfi4B3hEQwCejopqFZ3KOHje0ay9baF9z/SXeunQxla+MCMqC3dB/ruOno Snrg== 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=4kS78oXJZUGrKCzUZpGpGSSBJzhOYunPNUj2kwOzEgs=; b=kq2GmmMUwO+QML6XXj/WQkf8QMElIChvzbUznkUCyYPvud8n2m6YSRM/T4LMRrfcZu 5Rwn9xGMnkypfHFIhFMz1YTbk+TlkAa+L09ZL4aYwiOgfX0uUXrHGFFbgibtWN+tgXbV 2pLumayr5YX42EGQD0bgvxgO/76r08ct6ORtRG2qqkUvEhqWgrsjB+mTay1nwQOtKBEp zrhW/UO+i5Y5iNlxYekaSfB4MDZH2ZBzfLtSaOaN1GwElGvzit4RtLwLCLeESpelTZ1x OhdU8jccz7kU4wQdXeyDgz7FBX+xK2v5GLvuyynBBWmcvJB3IFac3Ps8LkohP9w97MdB CXSw== X-Gm-Message-State: APzg51AiYIq0o1WvoHK+XdVHsXcr/8NgV6QBlWkntoANZA3Ecuhb3cna bQ3gS+TTnIAS5bxow6ocUAtn92EYpD8kPg== X-Received: by 2002:a1c:a94d:: with SMTP id s74-v6mr5477409wme.39.1535980474522; Mon, 03 Sep 2018 06:14:34 -0700 (PDT) Received: from localhost (nat-35.starnet.cz. [178.255.168.35]) by smtp.gmail.com with ESMTPSA id t131-v6sm19273884wmg.10.2018.09.03.06.14.33 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Mon, 03 Sep 2018 06:14:34 -0700 (PDT) From: Michal Simek To: linux-kernel@vger.kernel.org, monstr@monstr.eu Cc: Jiri Slaby , linux-serial@vger.kernel.org, Greg Kroah-Hartman , linux-arm-kernel@lists.infradead.org Subject: [PATCH 2/2] serial: uartps: Change uart ID port allocation Date: Mon, 3 Sep 2018 15:14:30 +0200 Message-Id: <8ade255a03610abfe28538d5fdff4cf37848c552.1535980468.git.michal.simek@xilinx.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <0ee4683a7d3927c2ef20b1e106720e6154811cd7.1535980468.git.michal.simek@xilinx.com> References: <0ee4683a7d3927c2ef20b1e106720e6154811cd7.1535980468.git.michal.simek@xilinx.com> In-Reply-To: <0ee4683a7d3927c2ef20b1e106720e6154811cd7.1535980468.git.michal.simek@xilinx.com> References: <0ee4683a7d3927c2ef20b1e106720e6154811cd7.1535980468.git.michal.simek@xilinx.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- 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 | 106 ++++++++++++++++++++++++++++++++----- 1 file changed, 93 insertions(+), 13 deletions(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 71c032744dae..61c4a644e143 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,85 @@ 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; + + mutex_lock(&bitmap_lock); + + /* Alias list is stable that's why get alias bitmap only once */ + if (!alias_bitmap_initialized) { + of_alias_get_alias_list(cdns_uart_of_match, "serial", + alias_bitmap, MAX_UART_INSTANCES); + 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 +1481,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 +1520,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 +1661,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 +1687,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); -- 1.9.1