From patchwork Sat Sep 24 10:27:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 12987569 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 79889C6FA90 for ; Sat, 24 Sep 2022 10:29:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232732AbiIXK30 (ORCPT ); Sat, 24 Sep 2022 06:29:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41258 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230469AbiIXK3X (ORCPT ); Sat, 24 Sep 2022 06:29:23 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6571311ED77 for ; Sat, 24 Sep 2022 03:29:22 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 1E5A3B81028 for ; Sat, 24 Sep 2022 10:29:21 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9BAE1C43470; Sat, 24 Sep 2022 10:29:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664015359; bh=kOPdef61u9J3NjrGOgmrag2fBIjSFkVPOz6ll926H5Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dtC0+FwJhzSsxre81UO4oHzcdch/NQHtHTP5kosygArwuh/JFpsCA0+ooym5m9xlL rGeRV2H1+xCvSaRh8d2rP07omaTtSBZiTCiQ0zFxnD1pakCa4/CK100FTrCEvai7Na bEmsrMEqvkbVoFmKRywyJVw/jBC/O1DwMn758T69B+vN8JB3RaTKqNTvPFLS5dBQcu ptJUhx+BJNxjxeR7Ej5uBNvpQC/CRvU+z+uphOaXAqRemhzpj+7TAs2srXM7kS51/G 2UXyNVpOK4X4h2xBi1rFqgDg9oGV8/132a9n024JRiEooLD9s9+zjbArttjnHOs/Vd XCidMG6foOh1w== Received: by pali.im (Postfix) id 951051113; Sat, 24 Sep 2022 12:29:16 +0200 (CEST) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Johan Hovold , Greg Kroah-Hartman , =?utf-8?q?Marek_Beh=C3=BAn?= Cc: linux-usb@vger.kernel.org Subject: [PATCH v3 1/7] USB: serial: ftdi_sio: Fix divisor overflow Date: Sat, 24 Sep 2022 12:27:12 +0200 Message-Id: <20220924102718.2984-2-pali@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20220924102718.2984-1-pali@kernel.org> References: <20220924102718.2984-1-pali@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org The baud rate generating divisor is a 17-bit wide (14 bits integer part and 3 bits fractional part). Example: base clock = 48 MHz requested baud rate = 180 Baud divisor = 48,000,000 / (16 * 180) = 0b100000100011010.101 In this case the MSB gets discarded because of the overflow, and the actually used divisor will be 0b100011010.101 = 282.625, resulting in baud rate 10615 Baud, instead of the requested 180 Baud. The best possible thing to do in this case is to generate lowest possible baud rate (in the example it would be 183 Baud), by using maximum possible divisor. In case of divisor overflow, use maximum possible divisor. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Pali Rohár Tested-by: Marek Behún Signed-off-by: Marek Behún Cc: stable@vger.kernel.org --- drivers/usb/serial/ftdi_sio.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 52d59be92034..b2febe8d573a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1162,6 +1162,8 @@ static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) int divisor3 = DIV_ROUND_CLOSEST(base, 2 * baud); if ((divisor3 & 0x7) == 7) divisor3++; /* round x.7/8 up to x+1 */ + if (divisor3 > GENMASK(16, 0)) + divisor3 = GENMASK(16, 0); divisor = divisor3 >> 3; divisor3 &= 0x7; if (divisor3 == 1) @@ -1186,6 +1188,8 @@ static u32 ftdi_232bm_baud_base_to_divisor(int baud, int base) u32 divisor; /* divisor shifted 3 bits to the left */ int divisor3 = DIV_ROUND_CLOSEST(base, 2 * baud); + if (divisor3 > GENMASK(16, 0)) + divisor3 = GENMASK(16, 0); divisor = divisor3 >> 3; divisor |= (u32)divfrac[divisor3 & 0x7] << 14; /* Deal with special cases for highest baud rates. */ @@ -1209,6 +1213,8 @@ static u32 ftdi_2232h_baud_base_to_divisor(int baud, int base) /* hi-speed baud rate is 10-bit sampling instead of 16-bit */ divisor3 = DIV_ROUND_CLOSEST(8 * base, 10 * baud); + if (divisor3 > GENMASK(16, 0)) + divisor3 = GENMASK(16, 0); divisor = divisor3 >> 3; divisor |= (u32)divfrac[divisor3 & 0x7] << 14; From patchwork Sat Sep 24 10:27:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 12987565 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0019BC32771 for ; Sat, 24 Sep 2022 10:29:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231389AbiIXK3X (ORCPT ); Sat, 24 Sep 2022 06:29:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41240 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229495AbiIXK3W (ORCPT ); Sat, 24 Sep 2022 06:29:22 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5215311ED6A for ; Sat, 24 Sep 2022 03:29:21 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id D301F6124B for ; Sat, 24 Sep 2022 10:29:20 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1BC00C433B5; Sat, 24 Sep 2022 10:29:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664015360; bh=jS8PAUWdG58J8HZV3voE3Kk+kDMzClw8lsUzIiP6HVM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QRmpWXDqfBPOzumZ5uUbPV2sCWNC2Bdi4SaW2WVMon6GhMqQbhfF/eKuF7wjZKoqt j8BIJYBs2RRbR3v/Gavsl3WjxRNRC9biwlqzkwXnGnnbx5aeOvrQSJ39oigVDRU2Ao xkqf2cX996W+gcxVGCX3loJpjEcT4MOsxJC32zD2/lmfxeXv+K3A0lw7nMsb+wSyyV PwIgUje0U9EgFfj9To7lvDV0+TYIHO7XKv+492QHAfWeMFuaffwQdfbIvba1dhcrSf 6sOyNW42Qal9Gc2mJ6W0T22aJNDDnzYklR6KgkuJ97bbiELT55SBqx49fHqrXd/IXn Bh3EOY4nHq7kg== Received: by pali.im (Postfix) id 885941231; Sat, 24 Sep 2022 12:29:17 +0200 (CEST) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Johan Hovold , Greg Kroah-Hartman , =?utf-8?q?Marek_Beh=C3=BAn?= Cc: linux-usb@vger.kernel.org Subject: [PATCH v3 2/7] USB: serial: ftdi_sio: Add missing baud rate validation Date: Sat, 24 Sep 2022 12:27:13 +0200 Message-Id: <20220924102718.2984-3-pali@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20220924102718.2984-1-pali@kernel.org> References: <20220924102718.2984-1-pali@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Add lower checks for requested baud rate for FT8U232AM, FT232BM, FT2232C, FT232RL, FTX, FT2232H, FT4232H and FT232H. For all of these the minimum baud rate they can generate is 183 Baud. Signed-off-by: Pali Rohár Tested-by: Marek Behún Signed-off-by: Marek Behún --- drivers/usb/serial/ftdi_sio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index b2febe8d573a..bfa601fc14fe 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1335,7 +1335,7 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, } break; case FT8U232AM: /* 8U232AM chip */ - if (baud <= 3000000) { + if (baud >= 183 && baud <= 3000000) { div_value = ftdi_232am_baud_to_divisor(baud); } else { dev_dbg(dev, "%s - Baud rate too high!\n", __func__); @@ -1348,7 +1348,7 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, case FT2232C: /* FT2232C chip */ case FT232RL: /* FT232RL chip */ case FTX: /* FT-X series */ - if (baud <= 3000000) { + if (baud >= 183 && baud <= 3000000) { u16 product_id = le16_to_cpu( port->serial->dev->descriptor.idProduct); if (((product_id == FTDI_NDI_HUC_PID) || @@ -1372,7 +1372,7 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, case FT232H: /* FT232H chip */ if ((baud <= 12000000) && (baud >= 1200)) { div_value = ftdi_2232h_baud_to_divisor(baud); - } else if (baud < 1200) { + } else if (baud >= 183 && baud < 1200) { div_value = ftdi_232bm_baud_to_divisor(baud); } else { dev_dbg(dev, "%s - Baud rate too high!\n", __func__); From patchwork Sat Sep 24 10:27:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 12987570 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 231D5C6FA83 for ; Sat, 24 Sep 2022 10:29:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231327AbiIXK31 (ORCPT ); Sat, 24 Sep 2022 06:29:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41272 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231669AbiIXK3Y (ORCPT ); Sat, 24 Sep 2022 06:29:24 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B6DD211ED6A for ; Sat, 24 Sep 2022 03:29:23 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 72163B81025 for ; Sat, 24 Sep 2022 10:29:22 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0FC96C433C1; Sat, 24 Sep 2022 10:29:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664015361; bh=lwjnL2VFBJK0RItGN1P90Y2LCgSyc/zrZ+/ku7OexZE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=r+KWNXESXiCHVXYQeE54+diwma3MuJNc5zWxofcfEQB2Nl27BH4ibHXF9l9xWTk0o /90aUtBIzlEqjXRHifTtf33CmXGzHB5fgQgVz3xjVBhXC3yjWMOWPau1QoVVLvfXXk A7gZSs8LtDTgZOXHlesrv33mubdHMmmT/Lp/0yp5P/kBa2S8qLJiI0/WyjWmNXhUkl ALRyVPyWlbS7AHm+akfuHvH08jOX6c8aKfKYWNDHHpa6Q+NDLOojBxP/DHuch9UEjF VB+ZKq5yAZRE22aW6pVZch7bCjiTT6nSw8QHa/P1IXr15ieJ9mpv/zVv+eBgL624Fh Qc59gi6oJPC8Q== Received: by pali.im (Postfix) id 7C4C0127C; Sat, 24 Sep 2022 12:29:18 +0200 (CEST) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Johan Hovold , Greg Kroah-Hartman , =?utf-8?q?Marek_Beh=C3=BAn?= Cc: linux-usb@vger.kernel.org Subject: [PATCH v3 3/7] USB: serial: ftdi_sio: Extract SIO divisor code to function Date: Sat, 24 Sep 2022 12:27:14 +0200 Message-Id: <20220924102718.2984-4-pali@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20220924102718.2984-1-pali@kernel.org> References: <20220924102718.2984-1-pali@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org In preparation for following changes, extract divisor code for SIO chip into new function ftdi_sio_baud_to_divisor(), as is done for other chips. No functional change. Signed-off-by: Pali Rohár Tested-by: Marek Behún Signed-off-by: Marek Behún --- drivers/usb/serial/ftdi_sio.c | 45 ++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index bfa601fc14fe..fe8a7c5fa0e9 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1155,6 +1155,34 @@ static struct usb_serial_driver * const serial_drivers[] = { * *************************************************************************** */ +static u32 ftdi_sio_baud_to_divisor(int baud) +{ + switch (baud) { + case 300: + return ftdi_sio_b300; + case 600: + return ftdi_sio_b600; + case 1200: + return ftdi_sio_b1200; + case 2400: + return ftdi_sio_b2400; + case 4800: + return ftdi_sio_b4800; + case 9600: + return ftdi_sio_b9600; + case 19200: + return ftdi_sio_b19200; + case 38400: + return ftdi_sio_b38400; + case 57600: + return ftdi_sio_b57600; + case 115200: + return ftdi_sio_b115200; + default: + return -1; + } +} + static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) { unsigned short int divisor; @@ -1314,23 +1342,12 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, baud = 9600; switch (priv->chip_type) { case SIO: /* SIO chip */ - switch (baud) { - case 300: div_value = ftdi_sio_b300; break; - case 600: div_value = ftdi_sio_b600; break; - case 1200: div_value = ftdi_sio_b1200; break; - case 2400: div_value = ftdi_sio_b2400; break; - case 4800: div_value = ftdi_sio_b4800; break; - case 9600: div_value = ftdi_sio_b9600; break; - case 19200: div_value = ftdi_sio_b19200; break; - case 38400: div_value = ftdi_sio_b38400; break; - case 57600: div_value = ftdi_sio_b57600; break; - case 115200: div_value = ftdi_sio_b115200; break; - } /* baud */ - if (div_value == 0) { + div_value = ftdi_sio_baud_to_divisor(baud); + if (div_value == (u32)-1) { dev_dbg(dev, "%s - Baudrate (%d) requested is not supported\n", __func__, baud); - div_value = ftdi_sio_b9600; baud = 9600; + div_value = ftdi_sio_baud_to_divisor(baud); div_okay = 0; } break; From patchwork Sat Sep 24 10:27:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 12987567 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BEB1EC6FA83 for ; Sat, 24 Sep 2022 10:29:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231641AbiIXK3Y (ORCPT ); Sat, 24 Sep 2022 06:29:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41238 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229515AbiIXK3W (ORCPT ); Sat, 24 Sep 2022 06:29:22 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 22B1911ED67 for ; Sat, 24 Sep 2022 03:29:21 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id B2EE1611CC for ; Sat, 24 Sep 2022 10:29:20 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id BA01DC4347C; Sat, 24 Sep 2022 10:29:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664015360; bh=WeemlflOJmTQjkpMMZMOaJ74WI9we1Iyc69cTycNBls=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oOyWkXE7GYdJAxgGNoN+fGSjQqJgWbLmG41SSbLwb9d4VHRU0EwBOancnBaNjz62d e+CF6OzAFM4/3i5tbXDLrgccozMIbhX4RV6bBYplw+xJYwybM1+BiXgiejer8wtoHW SGTy+OjccAn+g472B22y1pA2jzbYI8GKB871uIcg25r97JA2bNJlCaXz6w3maUHrlp XtHzTD3tD6ycmOHYj8gaLlRmvBE9oq9vexXZDjyt1KypOoOTGIurHuSYx1T2IkNkIQ o5QlGuRPmxlnHv/M7kB28uqYw27BZ+rHpglWup9ggdVa5BGHn4XmcI0EPRZNsoDNju wohFwM62SnUMg== Received: by pali.im (Postfix) id 6FD8E8A2; Sat, 24 Sep 2022 12:29:19 +0200 (CEST) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Johan Hovold , Greg Kroah-Hartman , =?utf-8?q?Marek_Beh=C3=BAn?= Cc: linux-usb@vger.kernel.org Subject: [PATCH v3 4/7] USB: serial: ftdi_sio: Do not reset baud rate to 9600 Baud on error Date: Sat, 24 Sep 2022 12:27:15 +0200 Message-Id: <20220924102718.2984-5-pali@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20220924102718.2984-1-pali@kernel.org> References: <20220924102718.2984-1-pali@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org If setting new baud rate fails, some other drivers leave the device at previous baud rate, and ftdi_sio resets to 9600 Baud. Change this behavior to not reset baud rate to 9600. Signed-off-by: Pali Rohár Tested-by: Marek Behún Signed-off-by: Marek Behún --- drivers/usb/serial/ftdi_sio.c | 47 ++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index fe8a7c5fa0e9..1ab6bf48516f 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1315,7 +1315,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, static u32 get_ftdi_divisor(struct tty_struct *tty, - struct usb_serial_port *port) + struct usb_serial_port *port, speed_t old_baud) { struct ftdi_private *priv = usb_get_serial_port_data(port); struct device *dev = &port->dev; @@ -1338,6 +1338,8 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, __func__, priv->custom_divisor, baud); } + if (!baud) + baud = old_baud; if (!baud) baud = 9600; switch (priv->chip_type) { @@ -1346,8 +1348,12 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, if (div_value == (u32)-1) { dev_dbg(dev, "%s - Baudrate (%d) requested is not supported\n", __func__, baud); - baud = 9600; + baud = old_baud ? old_baud : 9600; div_value = ftdi_sio_baud_to_divisor(baud); + if (div_value == -1) { + baud = 9600; + div_value = ftdi_sio_baud_to_divisor(baud); + } div_okay = 0; } break; @@ -1356,8 +1362,11 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, div_value = ftdi_232am_baud_to_divisor(baud); } else { dev_dbg(dev, "%s - Baud rate too high!\n", __func__); - baud = 9600; - div_value = ftdi_232am_baud_to_divisor(9600); + if (old_baud >= 183 && old_baud <= 3000000) + baud = old_baud; + else + baud = 9600; + div_value = ftdi_232am_baud_to_divisor(baud); div_okay = 0; } break; @@ -1379,9 +1388,12 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, div_value = ftdi_232bm_baud_to_divisor(baud); } else { dev_dbg(dev, "%s - Baud rate too high!\n", __func__); - div_value = ftdi_232bm_baud_to_divisor(9600); + if (old_baud >= 183 && old_baud <= 3000000) + baud = old_baud; + else + baud = 9600; + div_value = ftdi_232bm_baud_to_divisor(baud); div_okay = 0; - baud = 9600; } break; case FT2232H: /* FT2232H chip */ @@ -1393,9 +1405,17 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, div_value = ftdi_232bm_baud_to_divisor(baud); } else { dev_dbg(dev, "%s - Baud rate too high!\n", __func__); - div_value = ftdi_232bm_baud_to_divisor(9600); + if (old_baud >= 183 && old_baud < 1200) { + baud = old_baud; + div_value = ftdi_232bm_baud_to_divisor(baud); + } else { + if (old_baud >= 1200 && old_baud <= 12000000) + baud = old_baud; + else + baud = 9600; + div_value = ftdi_2232h_baud_to_divisor(baud); + } div_okay = 0; - baud = 9600; } break; } /* priv->chip_type */ @@ -1410,7 +1430,7 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, return div_value; } -static int change_speed(struct tty_struct *tty, struct usb_serial_port *port) +static int change_speed(struct tty_struct *tty, struct usb_serial_port *port, speed_t old_baud) { struct ftdi_private *priv = usb_get_serial_port_data(port); u16 value; @@ -1418,7 +1438,7 @@ static int change_speed(struct tty_struct *tty, struct usb_serial_port *port) u32 index_value; int rv; - index_value = get_ftdi_divisor(tty, port); + index_value = get_ftdi_divisor(tty, port, old_baud); value = (u16)index_value; index = (u16)(index_value >> 16); if (priv->chip_type == FT2232C || priv->chip_type == FT2232H || @@ -1541,7 +1561,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss) if (priv->flags & ASYNC_SPD_MASK) dev_warn_ratelimited(&port->dev, "use of SPD flags is deprecated\n"); - change_speed(tty, port); + change_speed(tty, port, 9600); } mutex_unlock(&priv->cfg_lock); return 0; @@ -2790,9 +2810,12 @@ static void ftdi_set_termios(struct tty_struct *tty, /* Drop RTS and DTR */ clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } else { + speed_t old_baud = + old_termios ? tty_termios_baud_rate(old_termios) : 9600; + /* set the baudrate determined before */ mutex_lock(&priv->cfg_lock); - if (change_speed(tty, port)) + if (change_speed(tty, port, old_baud)) dev_err(ddev, "%s urb failed to set baudrate\n", __func__); mutex_unlock(&priv->cfg_lock); /* Ensure RTS and DTR are raised when baudrate changed from 0 */ From patchwork Sat Sep 24 10:27:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 12987568 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E5696C6FA92 for ; Sat, 24 Sep 2022 10:29:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232633AbiIXK30 (ORCPT ); Sat, 24 Sep 2022 06:29:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41244 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230168AbiIXK3W (ORCPT ); Sat, 24 Sep 2022 06:29:22 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DCBF611ED73 for ; Sat, 24 Sep 2022 03:29:21 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 7A0756124D for ; Sat, 24 Sep 2022 10:29:21 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id BEAFDC433D6; Sat, 24 Sep 2022 10:29:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664015360; bh=yx+JktSN6PeLt2CX0HE+os/dGWubiRJ91H/3H1rKS68=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BeaOXROCxdVFR6q9hElkT1aCu0xwpx89vQcyPJQETNoqmzOSjaNrg9s2Yqd7X7ouK i5HcINUYwGIj2xnytVOQWKwocspUvIBRLJxZur6P4p8E7f+ClbuTlGfD1hovkh8TwJ RG/fGmX8vl5QdD7AmR/DdyOZ1GRbFZ99Ys5yZgvpXMtSi1fruXuj+UyBlqos6zorZH xVZf6JxKz4UPAgwmjjzXg0WdRFGR6Mhr9rpHCZaxhAS6SweLI9f213QJKJnfQD4jXu Xmguz0u5bykzaXhXJ27PshriohfJPVRE102ySDdyofsx0LXQrKPxhaZN1K3zr+ayq8 zgoQBX7jFheNw== Received: by pali.im (Postfix) id 78EFC8A2; Sat, 24 Sep 2022 12:29:20 +0200 (CEST) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Johan Hovold , Greg Kroah-Hartman , =?utf-8?q?Marek_Beh=C3=BAn?= Cc: linux-usb@vger.kernel.org Subject: [PATCH v3 5/7] USB: serial: ftdi_sio: Fix baud rate rounding for ASYNC_SPD_CUST Date: Sat, 24 Sep 2022 12:27:16 +0200 Message-Id: <20220924102718.2984-6-pali@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20220924102718.2984-1-pali@kernel.org> References: <20220924102718.2984-1-pali@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org To compute more accurate baud rate when user uses ASYNC_SPD_CUST API, use DIV_ROUND_CLOSEST() instead of just rounding down. Rationale: Application uses old API, so it computes divisor D for baud rate B. The driver then tries to compute back the requested baud rate B, but rounds down in the division. Using rounding to closest value instead should increate accuracy here. Signed-off-by: Pali Rohár Tested-by: Marek Behún Signed-off-by: Marek Behún --- drivers/usb/serial/ftdi_sio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 1ab6bf48516f..718c86db2900 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1333,7 +1333,7 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, if (baud == 38400 && ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && (priv->custom_divisor)) { - baud = priv->baud_base / priv->custom_divisor; + baud = DIV_ROUND_CLOSEST(priv->baud_base, priv->custom_divisor); dev_dbg(dev, "%s - custom divisor %d sets baud rate to %d\n", __func__, priv->custom_divisor, baud); } From patchwork Sat Sep 24 10:27:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 12987572 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3A080C32771 for ; Sat, 24 Sep 2022 10:29:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231860AbiIXK31 (ORCPT ); Sat, 24 Sep 2022 06:29:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41260 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231258AbiIXK3X (ORCPT ); Sat, 24 Sep 2022 06:29:23 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7154C11ED78 for ; Sat, 24 Sep 2022 03:29:22 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 0D71B61257 for ; Sat, 24 Sep 2022 10:29:22 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id B2061C433D6; Sat, 24 Sep 2022 10:29:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664015361; bh=XK45Cba0A/NiOAoBGRSJ+KfBFQBEjtp6JE9DIB4zrBU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=P571yZbql/pvgOHEedQeWxdUkpLLGG5ZNm79//dloECAC4y1y3SAOv+redJXEL1lB Ra61ogz3K+zlsqCxMbhE32OsKk8+DPbGDsukGWZuAlFjrgQ/k7Hc8NcQqfoRvy61qe hycqLVL7LbwewKYrfw75hvdBQ4drcT7rVJDH7+gFmjuxQXZDNyYVsD6wKc+Y4ahAj/ DW4n/FkPhfkl5du671a2c3AEF+H5gApNEHYzVPzEN9kqdyBzd6KkeXKlgvNcTbTS++ oDN3DgeT7NCpvlbHQRtEBzXXKw/ENxqLxDg6Vi40FPVufaXBCPhsl+i72Uhrt3T8L4 zH4m17nnD6EbA== Received: by pali.im (Postfix) id 6C5448A2; Sat, 24 Sep 2022 12:29:21 +0200 (CEST) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Johan Hovold , Greg Kroah-Hartman , =?utf-8?q?Marek_Beh=C3=BAn?= Cc: linux-usb@vger.kernel.org Subject: [PATCH v3 6/7] USB: serial: ftdi_sio: Fix custom_divisor for TIOCGSERIAL and c_*speed for TCGETS2 Date: Sat, 24 Sep 2022 12:27:17 +0200 Message-Id: <20220924102718.2984-7-pali@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20220924102718.2984-1-pali@kernel.org> References: <20220924102718.2984-1-pali@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org When ASYNC_SPD_CUST is used, update custom_divisor field for TIOCGSERIAL and c_*speed fields for TCGETS2 so that they correspond to the newly set baud rate value. So userspace TCGETS2 ioctls in new c_*speed fields will see the true baud rate that is being used. This is needed for switching userspace applications to use TCGETS2 API as currently new c_*speed fields does not report correct values. Without this change userspace applications still have to use old deprecated TIOCGSERIAL to retrieve current baud rate. Signed-off-by: Pali Rohár Tested-by: Marek Behún Signed-off-by: Marek Behún --- Please note that if c_*speed fields of TCGETS2 are not going to be fixed then userspace application cannot be switched to use this new TCGETS2 API due to this issue. --- drivers/usb/serial/ftdi_sio.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 718c86db2900..79b00912c81c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1319,6 +1319,7 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, { struct ftdi_private *priv = usb_get_serial_port_data(port); struct device *dev = &port->dev; + int fix_custom_divisor = 0; u32 div_value = 0; int div_okay = 1; int baud; @@ -1333,6 +1334,7 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, if (baud == 38400 && ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && (priv->custom_divisor)) { + fix_custom_divisor = 1; baud = DIV_ROUND_CLOSEST(priv->baud_base, priv->custom_divisor); dev_dbg(dev, "%s - custom divisor %d sets baud rate to %d\n", __func__, priv->custom_divisor, baud); @@ -1426,7 +1428,19 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, ftdi_chip_name[priv->chip_type]); } + /* Fix deprecated async-compatible custom_divisor hack and update tty baud rate */ + if (fix_custom_divisor) { + priv->custom_divisor = DIV_ROUND_CLOSEST(priv->baud_base, baud); + old_baud = baud; + baud = 38400; + } + tty_encode_baud_rate(tty, baud, baud); + + /* For async-compatible custom_divisor store into TCGETS2 c_*speed fields real baud rate */ + if (fix_custom_divisor) + tty->termios.c_ispeed = tty->termios.c_ospeed = old_baud; + return div_value; } @@ -2699,6 +2713,8 @@ static void ftdi_set_termios(struct tty_struct *tty, dev_dbg(ddev, "%s: forcing baud rate for this device\n", __func__); tty_encode_baud_rate(tty, priv->force_baud, priv->force_baud); + termios->c_ispeed = termios->c_ospeed = + DIV_ROUND_CLOSEST(priv->baud_base, priv->custom_divisor); } /* Force RTS-CTS if this device requires it. */ From patchwork Sat Sep 24 10:27:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 12987571 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1412FC07E9D for ; Sat, 24 Sep 2022 10:29:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231739AbiIXK32 (ORCPT ); Sat, 24 Sep 2022 06:29:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41274 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231871AbiIXK3Z (ORCPT ); Sat, 24 Sep 2022 06:29:25 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 012AE11ED6C for ; Sat, 24 Sep 2022 03:29:24 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 91E86611D1 for ; Sat, 24 Sep 2022 10:29:23 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A73B4C433D7; Sat, 24 Sep 2022 10:29:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664015363; bh=2rW2Oa7PRK4CltmuQxwR4SI0g9BACdYXqf0KRtYdv20=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lJo2B0nRm3REhtD7sxVmjuwnlGA5HxYqzOc1mt4vLxhxaM1QMrR/DfjenTIp2HYpJ oK6P4ZlNpfZo60epAv4gZLwSLgmfzJT00onsdpmUKzo1Mcu7nKqCmagIObb/s431rf TLeEF+feSlWEQmiR57fetRIqvOcB4QAnwAQPQ8l0qXBWdQftEihp6ho/izvAFXsbhb M0I/lvTeABAUHXMWe9h+UhTD7U2MSqjMqmbVQYmXFuZX91RiOLI3QvdxFHCQQF6wVm ansrZOfTbKCed0nuhneGk1Hjbla0l7KWLRcaFjenvjOuovWRxD8P6iphXHRLGAj7v6 +W0KGbNBHXu8w== Received: by pali.im (Postfix) id 604A18A2; Sat, 24 Sep 2022 12:29:22 +0200 (CEST) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Johan Hovold , Greg Kroah-Hartman , =?utf-8?q?Marek_Beh=C3=BAn?= Cc: linux-usb@vger.kernel.org Subject: [PATCH v3 7/7] USB: serial: ftdi_sio: Fill c_*speed fields with real baud rate Date: Sat, 24 Sep 2022 12:27:18 +0200 Message-Id: <20220924102718.2984-8-pali@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20220924102718.2984-1-pali@kernel.org> References: <20220924102718.2984-1-pali@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Calculate baud rate value in c_*speed fields to the real values which were set on hardware. For this operation, add a new set of methods *_divisor_to_baud() for each chip and use them for calculating the real baud rate values. Each *_divisor_to_baud() method is constructed as an inverse function of its corresponding *_baud_to_divisor() method. Signed-off-by: Pali Rohár Tested-by: Marek Behún Signed-off-by: Marek Behún --- drivers/usb/serial/ftdi_sio.c | 93 +++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 79b00912c81c..350ed14b014c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1183,6 +1183,34 @@ static u32 ftdi_sio_baud_to_divisor(int baud) } } +static int ftdi_sdio_divisor_to_baud(u32 divisor) +{ + switch (divisor) { + case ftdi_sio_b300: + return 300; + case ftdi_sio_b600: + return 600; + case ftdi_sio_b1200: + return 1200; + case ftdi_sio_b2400: + return 2400; + case ftdi_sio_b4800: + return 4800; + case ftdi_sio_b9600: + return 9600; + case ftdi_sio_b19200: + return 19200; + case ftdi_sio_b38400: + return 38400; + case ftdi_sio_b57600: + return 57600; + case ftdi_sio_b115200: + return 115200; + default: + return 9600; + } +} + static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) { unsigned short int divisor; @@ -1205,11 +1233,28 @@ static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) return divisor; } +static int ftdi_232am_divisor_base_to_baud(unsigned short int divisor, int base) +{ + static const unsigned char divfrac_inv[4] = { 0, 4, 2, 1 }; + unsigned int divisor3; + + if (divisor == 0) + divisor = 1; + divisor3 = (GENMASK(13, 0) & divisor) << 3; + divisor3 |= divfrac_inv[(divisor >> 14) & 0x3]; + return DIV_ROUND_CLOSEST(base, 2 * divisor3); +} + static unsigned short int ftdi_232am_baud_to_divisor(int baud) { return ftdi_232am_baud_base_to_divisor(baud, 48000000); } +static int ftdi_232am_divisor_to_baud(unsigned short int divisor) +{ + return ftdi_232am_divisor_base_to_baud(divisor, 48000000); +} + static u32 ftdi_232bm_baud_base_to_divisor(int baud, int base) { static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; @@ -1228,11 +1273,31 @@ static u32 ftdi_232bm_baud_base_to_divisor(int baud, int base) return divisor; } +static int ftdi_232bm_divisor_base_to_baud(u32 divisor, int base) +{ + static const unsigned char divfrac_inv[8] = { 0, 4, 2, 1, 3, 5, 6, 7 }; + u32 divisor3; + + /* Deal with special cases for highest baud rates. */ + if (divisor == 0) + divisor = 1; /* 1.0 */ + else if (divisor == 1) + divisor = 0x4001; /* 1.5 */ + divisor3 = (GENMASK(13, 0) & divisor) << 3; + divisor3 |= divfrac_inv[(divisor >> 14) & 0x7]; + return DIV_ROUND_CLOSEST(base, 2 * divisor3); +} + static u32 ftdi_232bm_baud_to_divisor(int baud) { return ftdi_232bm_baud_base_to_divisor(baud, 48000000); } +static int ftdi_232bm_divisor_to_baud(u32 divisor) +{ + return ftdi_232bm_divisor_base_to_baud(divisor, 48000000); +} + static u32 ftdi_2232h_baud_base_to_divisor(int baud, int base) { static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; @@ -1260,11 +1325,32 @@ static u32 ftdi_2232h_baud_base_to_divisor(int baud, int base) return divisor; } +static int ftdi_2232h_divisor_base_to_baud(u32 divisor, int base) +{ + static const unsigned char divfrac_inv[8] = { 0, 4, 2, 1, 3, 5, 6, 7 }; + u32 divisor3; + + divisor &= GENMASK(16, 0); + /* Deal with special cases for highest baud rates. */ + if (divisor == 0) + divisor = 1; /* 1.0 */ + else if (divisor == 1) + divisor = 0x4001; /* 1.5 */ + divisor3 = (GENMASK(13, 0) & divisor) << 3; + divisor3 |= divfrac_inv[(divisor >> 14) & 0x7]; + return DIV_ROUND_CLOSEST(8 * base, 10 * divisor3); +} + static u32 ftdi_2232h_baud_to_divisor(int baud) { return ftdi_2232h_baud_base_to_divisor(baud, 120000000); } +static int ftdi_2232h_divisor_to_baud(u32 divisor) +{ + return ftdi_2232h_divisor_base_to_baud(divisor, 120000000); +} + #define set_mctrl(port, set) update_mctrl((port), (set), 0) #define clear_mctrl(port, clear) update_mctrl((port), 0, (clear)) @@ -1358,6 +1444,7 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, } div_okay = 0; } + baud = ftdi_sdio_divisor_to_baud(div_value); break; case FT8U232AM: /* 8U232AM chip */ if (baud >= 183 && baud <= 3000000) { @@ -1371,6 +1458,7 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, div_value = ftdi_232am_baud_to_divisor(baud); div_okay = 0; } + baud = ftdi_232am_divisor_to_baud(div_value); break; case FT232BM: /* FT232BM chip */ case FT2232C: /* FT2232C chip */ @@ -1397,25 +1485,30 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, div_value = ftdi_232bm_baud_to_divisor(baud); div_okay = 0; } + baud = ftdi_232bm_divisor_to_baud(div_value); break; case FT2232H: /* FT2232H chip */ case FT4232H: /* FT4232H chip */ case FT232H: /* FT232H chip */ if ((baud <= 12000000) && (baud >= 1200)) { div_value = ftdi_2232h_baud_to_divisor(baud); + baud = ftdi_2232h_divisor_to_baud(div_value); } else if (baud >= 183 && baud < 1200) { div_value = ftdi_232bm_baud_to_divisor(baud); + baud = ftdi_232bm_divisor_to_baud(div_value); } else { dev_dbg(dev, "%s - Baud rate too high!\n", __func__); if (old_baud >= 183 && old_baud < 1200) { baud = old_baud; div_value = ftdi_232bm_baud_to_divisor(baud); + baud = ftdi_232bm_divisor_to_baud(div_value); } else { if (old_baud >= 1200 && old_baud <= 12000000) baud = old_baud; else baud = 9600; div_value = ftdi_2232h_baud_to_divisor(baud); + baud = ftdi_2232h_divisor_to_baud(div_value); } div_okay = 0; }