[SERIAL] Clean up serial locking when obtaining a reference to a port

The locking for the uart_port is over complicated, and can be
simplified if we introduce a flag to indicate that a port is "dead"
and will be removed.

This also helps the validator because it removes a case of non-nested
unlock ordering.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>

authored by Russell King and committed by Russell King 68ac64cd e0a515bc

+61 -54
+60 -54
drivers/serial/serial_core.c
··· 1500 static struct uart_state *uart_get(struct uart_driver *drv, int line) 1501 { 1502 struct uart_state *state; 1503 1504 - mutex_lock(&port_mutex); 1505 state = drv->state + line; 1506 if (mutex_lock_interruptible(&state->mutex)) { 1507 - state = ERR_PTR(-ERESTARTSYS); 1508 - goto out; 1509 } 1510 1511 state->count++; 1512 - if (!state->port) { 1513 - state->count--; 1514 - mutex_unlock(&state->mutex); 1515 - state = ERR_PTR(-ENXIO); 1516 - goto out; 1517 } 1518 1519 if (!state->info) { ··· 1529 tasklet_init(&state->info->tlet, uart_tasklet_action, 1530 (unsigned long)state); 1531 } else { 1532 - state->count--; 1533 - mutex_unlock(&state->mutex); 1534 - state = ERR_PTR(-ENOMEM); 1535 } 1536 } 1537 - 1538 - out: 1539 - mutex_unlock(&port_mutex); 1540 return state; 1541 } 1542 1543 /* ··· 2085 } 2086 } 2087 2088 - /* 2089 - * This reverses the effects of uart_configure_port, hanging up the 2090 - * port before removal. 2091 - */ 2092 - static void 2093 - uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state) 2094 - { 2095 - struct uart_port *port = state->port; 2096 - struct uart_info *info = state->info; 2097 - 2098 - if (info && info->tty) 2099 - tty_vhangup(info->tty); 2100 - 2101 - mutex_lock(&state->mutex); 2102 - 2103 - state->info = NULL; 2104 - 2105 - /* 2106 - * Free the port IO and memory resources, if any. 2107 - */ 2108 - if (port->type != PORT_UNKNOWN) 2109 - port->ops->release_port(port); 2110 - 2111 - /* 2112 - * Indicate that there isn't a port here anymore. 2113 - */ 2114 - port->type = PORT_UNKNOWN; 2115 - 2116 - /* 2117 - * Kill the tasklet, and free resources. 2118 - */ 2119 - if (info) { 2120 - tasklet_kill(&info->tlet); 2121 - kfree(info); 2122 - } 2123 - 2124 - mutex_unlock(&state->mutex); 2125 - } 2126 - 2127 static struct tty_operations uart_ops = { 2128 .open = uart_open, 2129 .close = uart_close, ··· 2231 state = drv->state + port->line; 2232 2233 mutex_lock(&port_mutex); 2234 if (state->port) { 2235 ret = -EINVAL; 2236 goto out; ··· 2266 port->cons && !(port->cons->flags & CON_ENABLED)) 2267 register_console(port->cons); 2268 2269 out: 2270 mutex_unlock(&port_mutex); 2271 2272 return ret; ··· 2290 int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) 2291 { 2292 struct uart_state *state = drv->state + port->line; 2293 2294 BUG_ON(in_interrupt()); 2295 ··· 2301 mutex_lock(&port_mutex); 2302 2303 /* 2304 * Remove the devices from devfs 2305 */ 2306 tty_unregister_device(drv->tty_driver, port->line); 2307 2308 - uart_unconfigure_port(drv, state); 2309 state->port = NULL; 2310 mutex_unlock(&port_mutex); 2311
··· 1500 static struct uart_state *uart_get(struct uart_driver *drv, int line) 1501 { 1502 struct uart_state *state; 1503 + int ret = 0; 1504 1505 state = drv->state + line; 1506 if (mutex_lock_interruptible(&state->mutex)) { 1507 + ret = -ERESTARTSYS; 1508 + goto err; 1509 } 1510 1511 state->count++; 1512 + if (!state->port || state->port->flags & UPF_DEAD) { 1513 + ret = -ENXIO; 1514 + goto err_unlock; 1515 } 1516 1517 if (!state->info) { ··· 1531 tasklet_init(&state->info->tlet, uart_tasklet_action, 1532 (unsigned long)state); 1533 } else { 1534 + ret = -ENOMEM; 1535 + goto err_unlock; 1536 } 1537 } 1538 return state; 1539 + 1540 + err_unlock: 1541 + state->count--; 1542 + mutex_unlock(&state->mutex); 1543 + err: 1544 + return ERR_PTR(ret); 1545 } 1546 1547 /* ··· 2085 } 2086 } 2087 2088 static struct tty_operations uart_ops = { 2089 .open = uart_open, 2090 .close = uart_close, ··· 2270 state = drv->state + port->line; 2271 2272 mutex_lock(&port_mutex); 2273 + mutex_lock(&state->mutex); 2274 if (state->port) { 2275 ret = -EINVAL; 2276 goto out; ··· 2304 port->cons && !(port->cons->flags & CON_ENABLED)) 2305 register_console(port->cons); 2306 2307 + /* 2308 + * Ensure UPF_DEAD is not set. 2309 + */ 2310 + port->flags &= ~UPF_DEAD; 2311 + 2312 out: 2313 + mutex_unlock(&state->mutex); 2314 mutex_unlock(&port_mutex); 2315 2316 return ret; ··· 2322 int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) 2323 { 2324 struct uart_state *state = drv->state + port->line; 2325 + struct uart_info *info; 2326 2327 BUG_ON(in_interrupt()); 2328 ··· 2332 mutex_lock(&port_mutex); 2333 2334 /* 2335 + * Mark the port "dead" - this prevents any opens from 2336 + * succeeding while we shut down the port. 2337 + */ 2338 + mutex_lock(&state->mutex); 2339 + port->flags |= UPF_DEAD; 2340 + mutex_unlock(&state->mutex); 2341 + 2342 + /* 2343 * Remove the devices from devfs 2344 */ 2345 tty_unregister_device(drv->tty_driver, port->line); 2346 2347 + info = state->info; 2348 + if (info && info->tty) 2349 + tty_vhangup(info->tty); 2350 + 2351 + /* 2352 + * All users of this port should now be disconnected from 2353 + * this driver, and the port shut down. We should be the 2354 + * only thread fiddling with this port from now on. 2355 + */ 2356 + state->info = NULL; 2357 + 2358 + /* 2359 + * Free the port IO and memory resources, if any. 2360 + */ 2361 + if (port->type != PORT_UNKNOWN) 2362 + port->ops->release_port(port); 2363 + 2364 + /* 2365 + * Indicate that there isn't a port here anymore. 2366 + */ 2367 + port->type = PORT_UNKNOWN; 2368 + 2369 + /* 2370 + * Kill the tasklet, and free resources. 2371 + */ 2372 + if (info) { 2373 + tasklet_kill(&info->tlet); 2374 + kfree(info); 2375 + } 2376 + 2377 state->port = NULL; 2378 mutex_unlock(&port_mutex); 2379
+1
include/linux/serial_core.h
··· 254 #define UPF_CONS_FLOW ((__force upf_t) (1 << 23)) 255 #define UPF_SHARE_IRQ ((__force upf_t) (1 << 24)) 256 #define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28)) 257 #define UPF_IOREMAP ((__force upf_t) (1 << 31)) 258 259 #define UPF_CHANGE_MASK ((__force upf_t) (0x17fff))
··· 254 #define UPF_CONS_FLOW ((__force upf_t) (1 << 23)) 255 #define UPF_SHARE_IRQ ((__force upf_t) (1 << 24)) 256 #define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28)) 257 + #define UPF_DEAD ((__force upf_t) (1 << 30)) 258 #define UPF_IOREMAP ((__force upf_t) (1 << 31)) 259 260 #define UPF_CHANGE_MASK ((__force upf_t) (0x17fff))