From patchwork Wed Mar 15 10:28:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksey Makarov X-Patchwork-Id: 95330 Delivered-To: patch@linaro.org Received: by 10.140.89.134 with SMTP id v6csp259117qgd; Wed, 15 Mar 2017 03:33:33 -0700 (PDT) X-Received: by 10.84.128.74 with SMTP id 68mr3664244pla.111.1489574013419; Wed, 15 Mar 2017 03:33:33 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y76si1217012pfi.244.2017.03.15.03.33.33; Wed, 15 Mar 2017 03:33:33 -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=pass header.i=@linaro.org; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752885AbdCOKda (ORCPT + 25 others); Wed, 15 Mar 2017 06:33:30 -0400 Received: from mail-lf0-f48.google.com ([209.85.215.48]:36122 "EHLO mail-lf0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752501AbdCOKdZ (ORCPT ); Wed, 15 Mar 2017 06:33:25 -0400 Received: by mail-lf0-f48.google.com with SMTP id y193so4977568lfd.3 for ; Wed, 15 Mar 2017 03:33:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=TiX8XO3oBtxsVxnkc11EBJ+k1JPn8IBPiRG+xn1tlKE=; b=CQI939jsj7OO64jH+vS3l+wGPtAENdy4RZrFfpXVKRgZDTL756Si6zFKv6k8fhT9qL sKHzGqu0sX1fQELhmCVa+duiGENDkPUvP/NLkS07s8dMfjnhAIGZuQGP7xIo7Fl3AcEJ L/tc6jvhGDjBAf3DdrgZ2vZsF0GnXkCZfrXxA= 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=TiX8XO3oBtxsVxnkc11EBJ+k1JPn8IBPiRG+xn1tlKE=; b=Y79dS3S2lIpJtui1ae/HC7UQuakxRZqvPQdRNyAk/fAVWOyqdnI18eDMwrgYy8Coh6 cX+Cam+ic7uhw1MUAjMnDXD6F+3Wy93SfkjLU64zXAZxog2G8mr8eaoRbSVbJC3bGYOG 6CNwgJ3+jzgggEJfY9laJTtOEo39GLneEkr8HtNOLndQlGYzGrt9O3py++riy12i8eOW U4EOTRFaOCAv0sTjZNY8FfEDtZvKUuKhRA7W3OCWTh4sjg4ZPyv6eumZkRyatV3AEn2e HxNCdGtUtun93cVusatI6VQu5cEpSQEu9lfMSn90AMny+5DDylEEGAXNa7mFE6LnKQLn 5bww== X-Gm-Message-State: AFeK/H3SZ0pHqbBaxgFpGSMgiJZfl5aa/jKgz+8UCdIm2xepmvCO+MbHw8JN1P/fgBh6uTjw X-Received: by 10.25.169.80 with SMTP id s77mr798608lfe.119.1489574003219; Wed, 15 Mar 2017 03:33:23 -0700 (PDT) Received: from localhost.localdomain (nivc-213.auriga.ru. [80.240.102.213]) by smtp.gmail.com with ESMTPSA id 4sm265163ljf.33.2017.03.15.03.33.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 15 Mar 2017 03:33:22 -0700 (PDT) From: Aleksey Makarov To: linux-serial@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Aleksey Makarov , Sudeep Holla , Greg Kroah-Hartman , Peter Hurley , Jiri Slaby , Robin Murphy , Steven Rostedt , "Nair, Jayachandran" , Sergey Senozhatsky , Petr Mladek Subject: [PATCH v5 3/3] printk: fix double printing with earlycon Date: Wed, 15 Mar 2017 13:28:52 +0300 Message-Id: <20170315102854.1763-4-aleksey.makarov@linaro.org> X-Mailer: git-send-email 2.12.0 In-Reply-To: <20170315102854.1763-1-aleksey.makarov@linaro.org> References: <20170315102854.1763-1-aleksey.makarov@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org If a console was specified by ACPI SPCR table _and_ command line parameters like "console=ttyAMA0" _and_ "earlycon" were specified, then log messages appear twice. The root cause is that the code traverses the list of specified consoles (the `console_cmdline` array) and stops at the first match. But it may happen that the same console is referred by the elements of this array twice: pl011,mmio,0x87e024000000,115200 -- from SPCR ttyAMA0 -- from command line but in this case `preferred_console` points to the second entry and the flag CON_CONSDEV is not set, so bootconsole is not deregistered. To fix that, introduce an invariant "The last non-braille console is always the preferred one" on the entries of the console_cmdline array and don't try to check for double entries. Then traverse it in reverse order to be sure that if the console is preferred then it will be the first matching entry. Reported-by: Sudeep Holla Signed-off-by: Aleksey Makarov --- kernel/printk/printk.c | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) -- 2.12.0 diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index fd752f0c8ef1..7dc53b2831fb 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1902,20 +1902,25 @@ static int __add_preferred_console(char *name, int idx, char *options, int i; /* - * See if this tty is not yet registered, and - * if we have a slot free. + * Don't check if the console has already been registered, because it is + * pointless. After all, we can not check if two entries refer to + * the same console if one is matched with console->match(), and another + * by name/index: + * + * pl011,mmio,0x87e024000000,115200 -- added from SPCR + * ttyAMA0 -- added from command line + * + * Also this allows to maintain an invariant that will help to find if + * the matching console is preferred, see register_console(): + * + * The last non-braille console is always the preferred one. */ - for (i = 0, c = console_cmdline; - i < MAX_CMDLINECONSOLES && c->name[0]; - i++, c++) { - if (strcmp(c->name, name) == 0 && c->index == idx) { - if (!brl_options) - preferred_console = i; - return 0; - } - } + for (i = 0; i < MAX_CMDLINECONSOLES; i++) + if (!console_cmdline[i].name[0]) + break; if (i == MAX_CMDLINECONSOLES) return -E2BIG; + c = console_cmdline + i; if (!brl_options) preferred_console = i; strlcpy(c->name, name, sizeof(c->name)); @@ -2457,12 +2462,20 @@ void register_console(struct console *newcon) } /* - * See if this console matches one we selected on - * the command line. + * See if this console matches one we selected on the command line. + * + * The console_cmdline array is traversed in the reverse order because + * we want to be sure that if this console is preferred then it will be + * the first matching entry. We use the invariant that is maintained in + * __add_preferred_console(). */ - for (i = 0, c = console_cmdline; - i < MAX_CMDLINECONSOLES && c->name[0]; - i++, c++) { + for (i = MAX_CMDLINECONSOLES - 1; i >= 0; i--) { + + if (!console_cmdline[i].name[0]) + continue; + + c = console_cmdline + i; + if (!newcon->match || newcon->match(newcon, c->name, c->index, c->options) != 0) { /* default matching */