Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

serial: tegra-tcu: Reorder channel initialization

Request the RX mailbox only after initializing the UART data
structures. Otherwise it can rarely happen that the receive
callback is called before the UART is ready.

Fixes: 2d908b38d409 ("serial: Add Tegra Combined UART driver")
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Link: https://lore.kernel.org/r/20210609155655.3567545-1-mperttunen@nvidia.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Mikko Perttunen and committed by
Greg Kroah-Hartman
af9a1f61 08a84410

+15 -11
+15 -11
drivers/tty/serial/tegra-tcu.c
··· 195 195 return err; 196 196 } 197 197 198 - tcu->rx = mbox_request_channel_byname(&tcu->rx_client, "rx"); 199 - if (IS_ERR(tcu->rx)) { 200 - err = PTR_ERR(tcu->rx); 201 - dev_err(&pdev->dev, "failed to get rx mailbox: %d\n", err); 202 - goto free_tx; 203 - } 204 - 205 198 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE) 206 199 /* setup the console */ 207 200 strcpy(tcu->console.name, "ttyTCU"); ··· 219 226 if (err) { 220 227 dev_err(&pdev->dev, "failed to register UART driver: %d\n", 221 228 err); 222 - goto free_rx; 229 + goto free_tx; 223 230 } 224 231 225 232 /* setup the port */ ··· 239 246 goto unregister_uart; 240 247 } 241 248 249 + /* 250 + * Request RX channel after creating port to ensure tcu->port 251 + * is ready for any immediate incoming bytes. 252 + */ 253 + tcu->rx = mbox_request_channel_byname(&tcu->rx_client, "rx"); 254 + if (IS_ERR(tcu->rx)) { 255 + err = PTR_ERR(tcu->rx); 256 + dev_err(&pdev->dev, "failed to get rx mailbox: %d\n", err); 257 + goto remove_uart_port; 258 + } 259 + 242 260 platform_set_drvdata(pdev, tcu); 243 261 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE) 244 262 register_console(&tcu->console); ··· 257 253 258 254 return 0; 259 255 256 + remove_uart_port: 257 + uart_remove_one_port(&tcu->driver, &tcu->port); 260 258 unregister_uart: 261 259 uart_unregister_driver(&tcu->driver); 262 - free_rx: 263 - mbox_free_channel(tcu->rx); 264 260 free_tx: 265 261 mbox_free_channel(tcu->tx); 266 262 ··· 274 270 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE) 275 271 unregister_console(&tcu->console); 276 272 #endif 273 + mbox_free_channel(tcu->rx); 277 274 uart_remove_one_port(&tcu->driver, &tcu->port); 278 275 uart_unregister_driver(&tcu->driver); 279 - mbox_free_channel(tcu->rx); 280 276 mbox_free_channel(tcu->tx); 281 277 282 278 return 0;