@@ -2247,13 +2247,59 @@ static void serial8250_THRE_test(struct uart_port *port)
22472247 up -> bugs |= UART_BUG_THRE ;
22482248}
22492249
2250- int serial8250_do_startup (struct uart_port * port )
2250+ static void serial8250_initialize (struct uart_port * port )
22512251{
22522252 struct uart_8250_port * up = up_to_u8250p (port );
22532253 unsigned long flags ;
2254- unsigned char iir ;
2254+ bool lsr_TEMT , iir_NOINT ;
2255+
2256+ serial_port_out (port , UART_LCR , UART_LCR_WLEN8 );
2257+
2258+ uart_port_lock_irqsave (port , & flags );
2259+ if (port -> flags & UPF_FOURPORT ) {
2260+ if (!port -> irq )
2261+ port -> mctrl |= TIOCM_OUT1 ;
2262+ } else {
2263+ /* Most PC uarts need OUT2 raised to enable interrupts. */
2264+ if (port -> irq )
2265+ port -> mctrl |= TIOCM_OUT2 ;
2266+ }
2267+
2268+ serial8250_set_mctrl (port , port -> mctrl );
2269+
2270+ /*
2271+ * Serial over Lan (SoL) hack:
2272+ * Intel 8257x Gigabit ethernet chips have a 16550 emulation, to be used for Serial Over
2273+ * Lan. Those chips take a longer time than a normal serial device to signalize that a
2274+ * transmission data was queued. Due to that, the above test generally fails. One solution
2275+ * would be to delay the reading of iir. However, this is not reliable, since the timeout is
2276+ * variable. So, let's just don't test if we receive TX irq. This way, we'll never enable
2277+ * UART_BUG_TXEN.
2278+ */
2279+ if (!(port -> quirks & UPQ_NO_TXEN_TEST )) {
2280+ /* Do a quick test to see if we receive an interrupt when we enable the TX irq. */
2281+ serial_port_out (port , UART_IER , UART_IER_THRI );
2282+ lsr_TEMT = serial_port_in (port , UART_LSR ) & UART_LSR_TEMT ;
2283+ iir_NOINT = serial_port_in (port , UART_IIR ) & UART_IIR_NO_INT ;
2284+ serial_port_out (port , UART_IER , 0 );
2285+
2286+ if (lsr_TEMT && iir_NOINT ) {
2287+ if (!(up -> bugs & UART_BUG_TXEN )) {
2288+ up -> bugs |= UART_BUG_TXEN ;
2289+ dev_dbg (port -> dev , "enabling bad tx status workarounds\n" );
2290+ }
2291+ } else {
2292+ up -> bugs &= ~UART_BUG_TXEN ;
2293+ }
2294+ }
2295+
2296+ uart_port_unlock_irqrestore (port , flags );
2297+ }
2298+
2299+ int serial8250_do_startup (struct uart_port * port )
2300+ {
2301+ struct uart_8250_port * up = up_to_u8250p (port );
22552302 int retval ;
2256- u16 lsr ;
22572303
22582304 if (!port -> fifosize )
22592305 port -> fifosize = uart_config [port -> type ].fifo_size ;
@@ -2310,56 +2356,7 @@ int serial8250_do_startup(struct uart_port *port)
23102356
23112357 up -> ops -> setup_timer (up );
23122358
2313- /*
2314- * Now, initialize the UART
2315- */
2316- serial_port_out (port , UART_LCR , UART_LCR_WLEN8 );
2317-
2318- uart_port_lock_irqsave (port , & flags );
2319- if (up -> port .flags & UPF_FOURPORT ) {
2320- if (!up -> port .irq )
2321- up -> port .mctrl |= TIOCM_OUT1 ;
2322- } else
2323- /*
2324- * Most PC uarts need OUT2 raised to enable interrupts.
2325- */
2326- if (port -> irq )
2327- up -> port .mctrl |= TIOCM_OUT2 ;
2328-
2329- serial8250_set_mctrl (port , port -> mctrl );
2330-
2331- /*
2332- * Serial over Lan (SoL) hack:
2333- * Intel 8257x Gigabit ethernet chips have a 16550 emulation, to be
2334- * used for Serial Over Lan. Those chips take a longer time than a
2335- * normal serial device to signalize that a transmission data was
2336- * queued. Due to that, the above test generally fails. One solution
2337- * would be to delay the reading of iir. However, this is not
2338- * reliable, since the timeout is variable. So, let's just don't
2339- * test if we receive TX irq. This way, we'll never enable
2340- * UART_BUG_TXEN.
2341- */
2342- if (!(up -> port .quirks & UPQ_NO_TXEN_TEST )) {
2343- /*
2344- * Do a quick test to see if we receive an interrupt when we
2345- * enable the TX irq.
2346- */
2347- serial_port_out (port , UART_IER , UART_IER_THRI );
2348- lsr = serial_port_in (port , UART_LSR );
2349- iir = serial_port_in (port , UART_IIR );
2350- serial_port_out (port , UART_IER , 0 );
2351-
2352- if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT ) {
2353- if (!(up -> bugs & UART_BUG_TXEN )) {
2354- up -> bugs |= UART_BUG_TXEN ;
2355- dev_dbg (port -> dev , "enabling bad tx status workarounds\n" );
2356- }
2357- } else {
2358- up -> bugs &= ~UART_BUG_TXEN ;
2359- }
2360- }
2361-
2362- uart_port_unlock_irqrestore (port , flags );
2359+ serial8250_initialize (port );
23632360
23642361 /*
23652362 * Clear the interrupt registers again for luck, and clear the
0 commit comments