@@ -230,6 +230,8 @@ struct imx_port {
230
230
unsigned int saved_reg [10 ];
231
231
bool context_saved ;
232
232
233
+ bool last_putchar_was_newline ;
234
+
233
235
enum imx_tx_state tx_state ;
234
236
struct hrtimer trigger_start_tx ;
235
237
struct hrtimer trigger_stop_tx ;
@@ -2064,26 +2066,34 @@ static void imx_uart_console_putchar(struct uart_port *port, unsigned char ch)
2064
2066
barrier ();
2065
2067
2066
2068
imx_uart_writel (sport , ch , URTX0 );
2069
+
2070
+ sport -> last_putchar_was_newline = (ch == '\n' );
2067
2071
}
2068
2072
2069
- /*
2070
- * Interrupts are disabled on entering
2071
- */
2072
- static void
2073
- imx_uart_console_write (struct console * co , const char * s , unsigned int count )
2073
+ static void imx_uart_console_device_lock (struct console * co , unsigned long * flags )
2074
+ {
2075
+ struct uart_port * up = & imx_uart_ports [co -> index ]-> port ;
2076
+
2077
+ return __uart_port_lock_irqsave (up , flags );
2078
+ }
2079
+
2080
+ static void imx_uart_console_device_unlock (struct console * co , unsigned long flags )
2081
+ {
2082
+ struct uart_port * up = & imx_uart_ports [co -> index ]-> port ;
2083
+
2084
+ return __uart_port_unlock_irqrestore (up , flags );
2085
+ }
2086
+
2087
+ static void imx_uart_console_write_atomic (struct console * co ,
2088
+ struct nbcon_write_context * wctxt )
2074
2089
{
2075
2090
struct imx_port * sport = imx_uart_ports [co -> index ];
2091
+ struct uart_port * port = & sport -> port ;
2076
2092
struct imx_port_ucrs old_ucr ;
2077
- unsigned long flags ;
2078
2093
unsigned int ucr1 , usr2 ;
2079
- int locked = 1 ;
2080
2094
2081
- if (sport -> port .sysrq )
2082
- locked = 0 ;
2083
- else if (oops_in_progress )
2084
- locked = uart_port_trylock_irqsave (& sport -> port , & flags );
2085
- else
2086
- uart_port_lock_irqsave (& sport -> port , & flags );
2095
+ if (!nbcon_enter_unsafe (wctxt ))
2096
+ return ;
2087
2097
2088
2098
/*
2089
2099
* First, save UCR1/2/3 and then disable interrupts
@@ -2097,10 +2107,12 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count)
2097
2107
ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN );
2098
2108
2099
2109
imx_uart_writel (sport , ucr1 , UCR1 );
2100
-
2101
2110
imx_uart_writel (sport , old_ucr .ucr2 | UCR2_TXEN , UCR2 );
2102
2111
2103
- uart_console_write (& sport -> port , s , count , imx_uart_console_putchar );
2112
+ if (!sport -> last_putchar_was_newline )
2113
+ uart_console_write (port , "\n" , 1 , imx_uart_console_putchar );
2114
+ uart_console_write (port , wctxt -> outbuf , wctxt -> len ,
2115
+ imx_uart_console_putchar );
2104
2116
2105
2117
/*
2106
2118
* Finally, wait for transmitter to become empty
@@ -2110,8 +2122,73 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count)
2110
2122
0 , USEC_PER_SEC , false, sport , USR2 );
2111
2123
imx_uart_ucrs_restore (sport , & old_ucr );
2112
2124
2113
- if (locked )
2114
- uart_port_unlock_irqrestore (& sport -> port , flags );
2125
+ nbcon_exit_unsafe (wctxt );
2126
+ }
2127
+
2128
+ static void imx_uart_console_write_thread (struct console * co ,
2129
+ struct nbcon_write_context * wctxt )
2130
+ {
2131
+ struct imx_port * sport = imx_uart_ports [co -> index ];
2132
+ struct uart_port * port = & sport -> port ;
2133
+ struct imx_port_ucrs old_ucr ;
2134
+ unsigned int ucr1 , usr2 ;
2135
+
2136
+ if (!nbcon_enter_unsafe (wctxt ))
2137
+ return ;
2138
+
2139
+ /*
2140
+ * First, save UCR1/2/3 and then disable interrupts
2141
+ */
2142
+ imx_uart_ucrs_save (sport , & old_ucr );
2143
+ ucr1 = old_ucr .ucr1 ;
2144
+
2145
+ if (imx_uart_is_imx1 (sport ))
2146
+ ucr1 |= IMX1_UCR1_UARTCLKEN ;
2147
+ ucr1 |= UCR1_UARTEN ;
2148
+ ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN );
2149
+
2150
+ imx_uart_writel (sport , ucr1 , UCR1 );
2151
+ imx_uart_writel (sport , old_ucr .ucr2 | UCR2_TXEN , UCR2 );
2152
+
2153
+ if (nbcon_exit_unsafe (wctxt )) {
2154
+ int len = READ_ONCE (wctxt -> len );
2155
+ int i ;
2156
+
2157
+ /*
2158
+ * Write out the message. Toggle unsafe for each byte in order
2159
+ * to give another (higher priority) context the opportunity
2160
+ * for a friendly takeover. If such a takeover occurs, this
2161
+ * context must reacquire ownership in order to perform final
2162
+ * actions (such as re-enabling the interrupts).
2163
+ *
2164
+ * IMPORTANT: wctxt->outbuf and wctxt->len are no longer valid
2165
+ * after a reacquire so writing the message must be
2166
+ * aborted.
2167
+ */
2168
+ for (i = 0 ; i < len ; i ++ ) {
2169
+ if (!nbcon_enter_unsafe (wctxt ))
2170
+ break ;
2171
+
2172
+ uart_console_write (port , wctxt -> outbuf + i , 1 ,
2173
+ imx_uart_console_putchar );
2174
+
2175
+ if (!nbcon_exit_unsafe (wctxt ))
2176
+ break ;
2177
+ }
2178
+ }
2179
+
2180
+ while (!nbcon_enter_unsafe (wctxt ))
2181
+ nbcon_reacquire_nobuf (wctxt );
2182
+
2183
+ /*
2184
+ * Finally, wait for transmitter to become empty
2185
+ * and restore UCR1/2/3
2186
+ */
2187
+ read_poll_timeout (imx_uart_readl , usr2 , usr2 & USR2_TXDC ,
2188
+ 0 , USEC_PER_SEC , false, sport , USR2 );
2189
+ imx_uart_ucrs_restore (sport , & old_ucr );
2190
+
2191
+ nbcon_exit_unsafe (wctxt );
2115
2192
}
2116
2193
2117
2194
/*
@@ -2203,6 +2280,8 @@ imx_uart_console_setup(struct console *co, char *options)
2203
2280
if (retval )
2204
2281
goto error_console ;
2205
2282
2283
+ sport -> last_putchar_was_newline = true;
2284
+
2206
2285
if (options )
2207
2286
uart_parse_options (options , & baud , & parity , & bits , & flow );
2208
2287
else
@@ -2239,11 +2318,14 @@ imx_uart_console_exit(struct console *co)
2239
2318
static struct uart_driver imx_uart_uart_driver ;
2240
2319
static struct console imx_uart_console = {
2241
2320
.name = DEV_NAME ,
2242
- .write = imx_uart_console_write ,
2321
+ .write_atomic = imx_uart_console_write_atomic ,
2322
+ .write_thread = imx_uart_console_write_thread ,
2323
+ .device_lock = imx_uart_console_device_lock ,
2324
+ .device_unlock = imx_uart_console_device_unlock ,
2325
+ .flags = CON_PRINTBUFFER | CON_NBCON ,
2243
2326
.device = uart_console_device ,
2244
2327
.setup = imx_uart_console_setup ,
2245
2328
.exit = imx_uart_console_exit ,
2246
- .flags = CON_PRINTBUFFER ,
2247
2329
.index = -1 ,
2248
2330
.data = & imx_uart_uart_driver ,
2249
2331
};
0 commit comments