diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2006-12-08 05:39:03 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-08 11:28:58 -0500 |
commit | 42f6384fe4747f65dc27e8a5f96502204558203b (patch) | |
tree | 2426f001057d213fa89b0c2b790ddb93e4faa707 | |
parent | 927a6f9dd0d0b5f70cb2e0799ce7a3844f43d42f (diff) |
[PATCH] Char: sx, lock boards struct
Fix race condition which may occurs when multiple cards are probed at the same
time. Add mutex to critical sections to avoid this situation.
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/char/sx.c | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 50cd64262a13..42427f4d2ebd 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c | |||
@@ -298,6 +298,7 @@ static int sx_init_drivers(void); | |||
298 | 298 | ||
299 | static struct tty_driver *sx_driver; | 299 | static struct tty_driver *sx_driver; |
300 | 300 | ||
301 | static DEFINE_MUTEX(sx_boards_lock); | ||
301 | static struct sx_board boards[SX_NBOARDS]; | 302 | static struct sx_board boards[SX_NBOARDS]; |
302 | static struct sx_port *sx_ports; | 303 | static struct sx_port *sx_ports; |
303 | static int sx_initialized; | 304 | static int sx_initialized; |
@@ -1980,7 +1981,6 @@ static int sx_init_board (struct sx_board *board) | |||
1980 | } | 1981 | } |
1981 | 1982 | ||
1982 | if (chans) { | 1983 | if (chans) { |
1983 | /* board->flags |= SX_BOARD_PRESENT; */ | ||
1984 | if(board->irq > 0) { | 1984 | if(board->irq > 0) { |
1985 | /* fixed irq, probably PCI */ | 1985 | /* fixed irq, probably PCI */ |
1986 | if(sx_irqmask & (1 << board->irq)) { /* may we use this irq? */ | 1986 | if(sx_irqmask & (1 << board->irq)) { /* may we use this irq? */ |
@@ -2115,8 +2115,6 @@ static int __devinit probe_sx (struct sx_board *board) | |||
2115 | return 0; | 2115 | return 0; |
2116 | sx_dprintk (SX_DEBUG_INIT, "reset the board...\n"); | 2116 | sx_dprintk (SX_DEBUG_INIT, "reset the board...\n"); |
2117 | 2117 | ||
2118 | board->flags |= SX_BOARD_PRESENT; | ||
2119 | |||
2120 | func_exit(); | 2118 | func_exit(); |
2121 | return 1; | 2119 | return 1; |
2122 | } | 2120 | } |
@@ -2211,8 +2209,6 @@ static int __devinit probe_si (struct sx_board *board) | |||
2211 | return 0; | 2209 | return 0; |
2212 | sx_dprintk (SX_DEBUG_INIT, "reset the board...\n"); | 2210 | sx_dprintk (SX_DEBUG_INIT, "reset the board...\n"); |
2213 | 2211 | ||
2214 | board->flags |= SX_BOARD_PRESENT; | ||
2215 | |||
2216 | func_exit(); | 2212 | func_exit(); |
2217 | return 1; | 2213 | return 1; |
2218 | } | 2214 | } |
@@ -2396,10 +2392,15 @@ static int __devinit sx_eisa_probe(struct device *dev) | |||
2396 | unsigned int i; | 2392 | unsigned int i; |
2397 | int retval = -EIO; | 2393 | int retval = -EIO; |
2398 | 2394 | ||
2395 | mutex_lock(&sx_boards_lock); | ||
2399 | i = sx_find_free_board(); | 2396 | i = sx_find_free_board(); |
2400 | 2397 | if (i == SX_NBOARDS) { | |
2401 | if (i == SX_NBOARDS) | 2398 | mutex_unlock(&sx_boards_lock); |
2402 | goto err; | 2399 | goto err; |
2400 | } | ||
2401 | board = &boards[i]; | ||
2402 | board->flags |= SX_BOARD_PRESENT; | ||
2403 | mutex_unlock(&sx_boards_lock); | ||
2403 | 2404 | ||
2404 | dev_info(dev, "XIO : Signature found in EISA slot %lu, " | 2405 | dev_info(dev, "XIO : Signature found in EISA slot %lu, " |
2405 | "Product %d Rev %d (REPORT THIS TO LKLM)\n", | 2406 | "Product %d Rev %d (REPORT THIS TO LKLM)\n", |
@@ -2407,7 +2408,6 @@ static int __devinit sx_eisa_probe(struct device *dev) | |||
2407 | inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2), | 2408 | inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2), |
2408 | inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3)); | 2409 | inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3)); |
2409 | 2410 | ||
2410 | board = &boards[i]; | ||
2411 | board->eisa_base = eisa_slot; | 2411 | board->eisa_base = eisa_slot; |
2412 | board->flags &= ~SX_BOARD_TYPE; | 2412 | board->flags &= ~SX_BOARD_TYPE; |
2413 | board->flags |= SI_EISA_BOARD; | 2413 | board->flags |= SI_EISA_BOARD; |
@@ -2430,6 +2430,7 @@ static int __devinit sx_eisa_probe(struct device *dev) | |||
2430 | return 0; | 2430 | return 0; |
2431 | err_unmap: | 2431 | err_unmap: |
2432 | iounmap(board->base); | 2432 | iounmap(board->base); |
2433 | board->flags &= ~SX_BOARD_PRESENT; | ||
2433 | err: | 2434 | err: |
2434 | return retval; | 2435 | return retval; |
2435 | } | 2436 | } |
@@ -2498,16 +2499,19 @@ static int __devinit sx_pci_probe(struct pci_dev *pdev, | |||
2498 | unsigned int i; | 2499 | unsigned int i; |
2499 | int retval = -EIO; | 2500 | int retval = -EIO; |
2500 | 2501 | ||
2502 | mutex_lock(&sx_boards_lock); | ||
2501 | i = sx_find_free_board(); | 2503 | i = sx_find_free_board(); |
2502 | 2504 | if (i == SX_NBOARDS) { | |
2503 | if (i == SX_NBOARDS) | 2505 | mutex_unlock(&sx_boards_lock); |
2504 | goto err; | 2506 | goto err; |
2507 | } | ||
2508 | board = &boards[i]; | ||
2509 | board->flags |= SX_BOARD_PRESENT; | ||
2510 | mutex_unlock(&sx_boards_lock); | ||
2505 | 2511 | ||
2506 | retval = pci_enable_device(pdev); | 2512 | retval = pci_enable_device(pdev); |
2507 | if (retval) | 2513 | if (retval) |
2508 | goto err; | 2514 | goto err_flag; |
2509 | |||
2510 | board = &boards[i]; | ||
2511 | 2515 | ||
2512 | board->flags &= ~SX_BOARD_TYPE; | 2516 | board->flags &= ~SX_BOARD_TYPE; |
2513 | board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD : | 2517 | board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD : |
@@ -2522,7 +2526,7 @@ static int __devinit sx_pci_probe(struct pci_dev *pdev, | |||
2522 | board->base = ioremap(board->hw_base, WINDOW_LEN (board)); | 2526 | board->base = ioremap(board->hw_base, WINDOW_LEN (board)); |
2523 | if (!board->base) { | 2527 | if (!board->base) { |
2524 | dev_err(&pdev->dev, "ioremap failed\n"); | 2528 | dev_err(&pdev->dev, "ioremap failed\n"); |
2525 | goto err; | 2529 | goto err_flag; |
2526 | } | 2530 | } |
2527 | 2531 | ||
2528 | /* Most of the stuff on the CF board is offset by 0x18000 .... */ | 2532 | /* Most of the stuff on the CF board is offset by 0x18000 .... */ |
@@ -2546,6 +2550,8 @@ static int __devinit sx_pci_probe(struct pci_dev *pdev, | |||
2546 | return 0; | 2550 | return 0; |
2547 | err_unmap: | 2551 | err_unmap: |
2548 | iounmap(board->base2); | 2552 | iounmap(board->base2); |
2553 | err_flag: | ||
2554 | board->flags &= ~SX_BOARD_PRESENT; | ||
2549 | err: | 2555 | err: |
2550 | return retval; | 2556 | return retval; |
2551 | } | 2557 | } |
@@ -2611,6 +2617,7 @@ static int __init sx_init(void) | |||
2611 | board->irq = sx_irqmask?-1:0; | 2617 | board->irq = sx_irqmask?-1:0; |
2612 | 2618 | ||
2613 | if (probe_sx (board)) { | 2619 | if (probe_sx (board)) { |
2620 | board->flags |= SX_BOARD_PRESENT; | ||
2614 | found++; | 2621 | found++; |
2615 | } else { | 2622 | } else { |
2616 | iounmap(board->base); | 2623 | iounmap(board->base); |
@@ -2627,6 +2634,7 @@ static int __init sx_init(void) | |||
2627 | board->irq = sx_irqmask ?-1:0; | 2634 | board->irq = sx_irqmask ?-1:0; |
2628 | 2635 | ||
2629 | if (probe_si (board)) { | 2636 | if (probe_si (board)) { |
2637 | board->flags |= SX_BOARD_PRESENT; | ||
2630 | found++; | 2638 | found++; |
2631 | } else { | 2639 | } else { |
2632 | iounmap (board->base); | 2640 | iounmap (board->base); |
@@ -2642,6 +2650,7 @@ static int __init sx_init(void) | |||
2642 | board->irq = sx_irqmask ?-1:0; | 2650 | board->irq = sx_irqmask ?-1:0; |
2643 | 2651 | ||
2644 | if (probe_si (board)) { | 2652 | if (probe_si (board)) { |
2653 | board->flags |= SX_BOARD_PRESENT; | ||
2645 | found++; | 2654 | found++; |
2646 | } else { | 2655 | } else { |
2647 | iounmap (board->base); | 2656 | iounmap (board->base); |