From patchwork Thu Dec 21 23:18:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hugo Villeneuve X-Patchwork-Id: 182470 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:2483:b0:fb:cd0c:d3e with SMTP id q3csp742531dyi; Thu, 21 Dec 2023 15:19:55 -0800 (PST) X-Google-Smtp-Source: AGHT+IHqw0YNesLsvsFWAiLU9orDguNDtomIFcq0t5bWheP8+lDb+zglb6eiyhQEQwptN+03ismT X-Received: by 2002:ad4:5fc5:0:b0:67f:9179:5415 with SMTP id jq5-20020ad45fc5000000b0067f91795415mr443605qvb.24.1703200795136; Thu, 21 Dec 2023 15:19:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1703200795; cv=none; d=google.com; s=arc-20160816; b=MbG1l6ZJ57NSdaXbCb+GMRirjZy/4fmsgXVMEnmMLR1k/dxdfFFTmt5uDJnULxN6gZ 6kwdM9AnAvYfsZ+LteM5dsZhnzM/h5kdMue4v/mp7r5kwEKWjH21gunE/1ebNu3MmkRn mqr0LWqACnVxz9daDFO3rN2NGUijJFSrZB0fx/bXiVTKFWf0Dc/PYnQV6OYY3Uh9QNYE eLyGAgj0Cl6We8gyngVSmLgcRvcUir4vOp0e7lEzT5Dth6EV9DqLxvA18EzkfgsynXZt B4IDVAfFZLfi+W8QFzupsmxVHIFvoGNO5mW440Z3duLEotKq9yUhm09H6uCLlX0DeZjo SaiQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=subject:content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:cc:to:from:dkim-signature; bh=zFCvSODRlDhyfhkyYaxqYDprC5OQrJQqCGo9MKePm3A=; fh=wezBxLKzeP89QLmtFJW/GbF5DMoLbBZvPQWVRfEqBGE=; b=bzjb9/vrwAkiRjl8aNqOzIAECtOzmm4Pl1voBG00UeNdOPW3H7SL1JfF1QTvshVSjl 7Pg8ZJZf99pKx0e4gHc+DnZRTrnK3UQ5qXjlsTd0xpo/dZuNaMxdKbM1+7vmwscI8gm6 bAFpY781L8y1I/IljjE4vnr7ARpFX8E4iP7tO/4GNz85Nq+kvbhfMYwkhusOoB6HhAtg gVdrvof2dUSBD4TXmemYagMIphJhena7jgBBt8sFDfLX7+LfN4R7i5O4RYXvGyK39wDi pISNdAiOi+o4Z0k94P9eSDoKVKlzFKDFojQ0W1g1Ki9/5QbnpCFOCiKBgHXKFKcT3Kxi r3Qg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@hugovil.com header.s=x header.b=YZmyiQCH; spf=pass (google.com: domain of linux-kernel+bounces-9159-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-9159-ouuuleilei=gmail.com@vger.kernel.org" Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id b17-20020a0cf051000000b0067f61745971si701575qvl.432.2023.12.21.15.19.55 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Dec 2023 15:19:55 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-9159-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@hugovil.com header.s=x header.b=YZmyiQCH; spf=pass (google.com: domain of linux-kernel+bounces-9159-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-9159-ouuuleilei=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id AD9D61C20D74 for ; Thu, 21 Dec 2023 23:19:53 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 732CA7AE93; Thu, 21 Dec 2023 23:18:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=hugovil.com header.i=@hugovil.com header.b="YZmyiQCH" X-Original-To: linux-kernel@vger.kernel.org Received: from mail.hugovil.com (mail.hugovil.com [162.243.120.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B861078E8F; Thu, 21 Dec 2023 23:18:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hugovil.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=hugovil.com DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=hugovil.com ; s=x; h=Subject:Content-Transfer-Encoding:MIME-Version:Message-Id:Date:Cc:To :From:subject:date:message-id:reply-to; bh=zFCvSODRlDhyfhkyYaxqYDprC5OQrJQqCGo9MKePm3A=; b=YZmyiQCHE5e0ItphwBphKivjgL nVggYMT39w3kM1I/N43fofJjfKo4DXFbuQjJgZEqHiBEJ4R+CfdrCY8onz3tqcghDErcE0V5v1LWs lAlxUVMKR3FmJgkdZ4qcg0kkG+CEe6KmW108t33MEu3/gUzf7wmfZNfKiajkRFYHmni0=; Received: from modemcable168.174-80-70.mc.videotron.ca ([70.80.174.168]:52484 helo=pettiford.lan) by mail.hugovil.com with esmtpa (Exim 4.92) (envelope-from ) id 1rGSJF-00025W-G7; Thu, 21 Dec 2023 18:18:34 -0500 From: Hugo Villeneuve To: gregkh@linuxfoundation.org, jirislaby@kernel.org, kubakici@wp.pl, indrakanti_ram@hotmail.com, phil@raspberrypi.org Cc: linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org, hugo@hugovil.com, Hugo Villeneuve , stable@vger.kernel.org, Yury Norov Date: Thu, 21 Dec 2023 18:18:08 -0500 Message-Id: <20231221231823.2327894-2-hugo@hugovil.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231221231823.2327894-1-hugo@hugovil.com> References: <20231221231823.2327894-1-hugo@hugovil.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-SA-Exim-Connect-IP: 70.80.174.168 X-SA-Exim-Mail-From: hugo@hugovil.com X-Spam-Level: X-Spam-Report: * -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP * -0.0 T_SCC_BODY_TEXT_LINE No description available. Subject: [PATCH v2 01/16] serial: sc16is7xx: fix invalid sc16is7xx_lines bitfield in case of probe error X-SA-Exim-Version: 4.2.1 (built Wed, 08 May 2019 21:11:16 +0000) X-SA-Exim-Scanned: Yes (on mail.hugovil.com) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1785935476532932090 X-GMAIL-MSGID: 1785935476532932090 From: Hugo Villeneuve If an error occurs during probing, the sc16is7xx_lines bitfield may be left in a state that doesn't represent the correct state of lines allocation. For example, in a system with two SC16 devices, if an error occurs only during probing of channel (port) B of the second device, sc16is7xx_lines final state will be 00001011b instead of the expected 00000011b. This is caused in part because of the "i--" in the for/loop located in the out_ports: error path. Fix this by checking the return value of uart_add_one_port() and set line allocation bit only if this was successful. This allows the refactor of the obfuscated for(i--...) loop in the error path, and properly call uart_remove_one_port() only when needed, and properly unset line allocation bits. Also use same mechanism in remove() when calling uart_remove_one_port(). Fixes: c64349722d14 ("sc16is7xx: support multiple devices") Cc: stable@vger.kernel.org Cc: Yury Norov Signed-off-by: Hugo Villeneuve --- drivers/tty/serial/sc16is7xx.c | 44 ++++++++++++++-------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index e40e4a99277e..17b90f971f96 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -407,19 +407,6 @@ static void sc16is7xx_port_update(struct uart_port *port, u8 reg, regmap_update_bits(one->regmap, reg, mask, val); } -static int sc16is7xx_alloc_line(void) -{ - int i; - - BUILD_BUG_ON(SC16IS7XX_MAX_DEVS > BITS_PER_LONG); - - for (i = 0; i < SC16IS7XX_MAX_DEVS; i++) - if (!test_and_set_bit(i, &sc16is7xx_lines)) - break; - - return i; -} - static void sc16is7xx_power(struct uart_port *port, int on) { sc16is7xx_port_update(port, SC16IS7XX_IER_REG, @@ -1550,6 +1537,13 @@ static int sc16is7xx_probe(struct device *dev, SC16IS7XX_IOCONTROL_SRESET_BIT); for (i = 0; i < devtype->nr_uart; ++i) { + s->p[i].port.line = find_first_zero_bit(&sc16is7xx_lines, + SC16IS7XX_MAX_DEVS); + if (s->p[i].port.line >= SC16IS7XX_MAX_DEVS) { + ret = -ERANGE; + goto out_ports; + } + /* Initialize port data */ s->p[i].port.dev = dev; s->p[i].port.irq = irq; @@ -1569,14 +1563,8 @@ static int sc16is7xx_probe(struct device *dev, s->p[i].port.rs485_supported = sc16is7xx_rs485_supported; s->p[i].port.ops = &sc16is7xx_ops; s->p[i].old_mctrl = 0; - s->p[i].port.line = sc16is7xx_alloc_line(); s->p[i].regmap = regmaps[i]; - if (s->p[i].port.line >= SC16IS7XX_MAX_DEVS) { - ret = -ENOMEM; - goto out_ports; - } - mutex_init(&s->p[i].efr_lock); ret = uart_get_rs485_mode(&s->p[i].port); @@ -1594,8 +1582,13 @@ static int sc16is7xx_probe(struct device *dev, kthread_init_work(&s->p[i].tx_work, sc16is7xx_tx_proc); kthread_init_work(&s->p[i].reg_work, sc16is7xx_reg_proc); kthread_init_delayed_work(&s->p[i].ms_work, sc16is7xx_ms_proc); + /* Register port */ - uart_add_one_port(&sc16is7xx_uart, &s->p[i].port); + ret = uart_add_one_port(&sc16is7xx_uart, &s->p[i].port); + if (ret) + goto out_ports; + + set_bit(s->p[i].port.line, &sc16is7xx_lines); /* Enable EFR */ sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_LCR_REG, @@ -1653,10 +1646,9 @@ static int sc16is7xx_probe(struct device *dev, #endif out_ports: - for (i--; i >= 0; i--) { - uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port); - clear_bit(s->p[i].port.line, &sc16is7xx_lines); - } + for (i = 0; i < devtype->nr_uart; i++) + if (test_and_clear_bit(s->p[i].port.line, &sc16is7xx_lines)) + uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port); kthread_stop(s->kworker_task); @@ -1678,8 +1670,8 @@ static void sc16is7xx_remove(struct device *dev) for (i = 0; i < s->devtype->nr_uart; i++) { kthread_cancel_delayed_work_sync(&s->p[i].ms_work); - uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port); - clear_bit(s->p[i].port.line, &sc16is7xx_lines); + if (test_and_clear_bit(s->p[i].port.line, &sc16is7xx_lines)) + uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port); sc16is7xx_power(&s->p[i].port, 0); }