Commit 9e17df37d710f8998e9cb10a548304fe33d4a5c2
Committed by
Greg Kroah-Hartman
1 parent
f30e826069
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
tty: mxser: improve error handling in mxser_probe() and mxser_module_init()
1. Currently mxser_probe() and mxser_module_init() ignore errors that can happen in tty_port_register_device(). 2. mxser_module_init() does not deallocate resources allocated in mxser_get_ISA_conf() if mxser_initbrd() failed. The patch adds proper error handling in all the cases. Also it moves free_irq() from mxser_release_ISA_res() to mxser_board_remove(), since it makes mxser_release_ISA_res() a counterpart for mxser_get_ISA_conf(), while free_irq() is relevant to both ISA and PCI boards. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 1 changed file with 35 additions and 7 deletions Side-by-side Diff
drivers/tty/mxser.c
... | ... | @@ -2364,7 +2364,6 @@ |
2364 | 2364 | |
2365 | 2365 | static void mxser_release_ISA_res(struct mxser_board *brd) |
2366 | 2366 | { |
2367 | - free_irq(brd->irq, brd); | |
2368 | 2367 | release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); |
2369 | 2368 | mxser_release_vector(brd); |
2370 | 2369 | } |
... | ... | @@ -2430,6 +2429,7 @@ |
2430 | 2429 | tty_unregister_device(mxvar_sdriver, brd->idx + i); |
2431 | 2430 | tty_port_destroy(&brd->ports[i].port); |
2432 | 2431 | } |
2432 | + free_irq(brd->irq, brd); | |
2433 | 2433 | } |
2434 | 2434 | |
2435 | 2435 | static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) |
... | ... | @@ -2554,6 +2554,7 @@ |
2554 | 2554 | struct mxser_board *brd; |
2555 | 2555 | unsigned int i, j; |
2556 | 2556 | unsigned long ioaddress; |
2557 | + struct device *tty_dev; | |
2557 | 2558 | int retval = -EINVAL; |
2558 | 2559 | |
2559 | 2560 | for (i = 0; i < MXSER_BOARDS; i++) |
2560 | 2561 | |
... | ... | @@ -2637,13 +2638,25 @@ |
2637 | 2638 | if (retval) |
2638 | 2639 | goto err_rel3; |
2639 | 2640 | |
2640 | - for (i = 0; i < brd->info->nports; i++) | |
2641 | - tty_port_register_device(&brd->ports[i].port, mxvar_sdriver, | |
2642 | - brd->idx + i, &pdev->dev); | |
2641 | + for (i = 0; i < brd->info->nports; i++) { | |
2642 | + tty_dev = tty_port_register_device(&brd->ports[i].port, | |
2643 | + mxvar_sdriver, brd->idx + i, &pdev->dev); | |
2644 | + if (IS_ERR(tty_dev)) { | |
2645 | + retval = PTR_ERR(tty_dev); | |
2646 | + for (i--; i >= 0; i--) | |
2647 | + tty_unregister_device(mxvar_sdriver, | |
2648 | + brd->idx + i); | |
2649 | + goto err_relbrd; | |
2650 | + } | |
2651 | + } | |
2643 | 2652 | |
2644 | 2653 | pci_set_drvdata(pdev, brd); |
2645 | 2654 | |
2646 | 2655 | return 0; |
2656 | +err_relbrd: | |
2657 | + for (i = 0; i < brd->info->nports; i++) | |
2658 | + tty_port_destroy(&brd->ports[i].port); | |
2659 | + free_irq(brd->irq, brd); | |
2647 | 2660 | err_rel3: |
2648 | 2661 | pci_release_region(pdev, 3); |
2649 | 2662 | err_zero: |
... | ... | @@ -2665,7 +2678,6 @@ |
2665 | 2678 | |
2666 | 2679 | mxser_board_remove(brd); |
2667 | 2680 | |
2668 | - free_irq(pdev->irq, brd); | |
2669 | 2681 | pci_release_region(pdev, 2); |
2670 | 2682 | pci_release_region(pdev, 3); |
2671 | 2683 | pci_disable_device(pdev); |
... | ... | @@ -2683,6 +2695,7 @@ |
2683 | 2695 | static int __init mxser_module_init(void) |
2684 | 2696 | { |
2685 | 2697 | struct mxser_board *brd; |
2698 | + struct device *tty_dev; | |
2686 | 2699 | unsigned int b, i, m; |
2687 | 2700 | int retval; |
2688 | 2701 | |
2689 | 2702 | |
2690 | 2703 | |
... | ... | @@ -2728,14 +2741,29 @@ |
2728 | 2741 | |
2729 | 2742 | /* mxser_initbrd will hook ISR. */ |
2730 | 2743 | if (mxser_initbrd(brd, NULL) < 0) { |
2744 | + mxser_release_ISA_res(brd); | |
2731 | 2745 | brd->info = NULL; |
2732 | 2746 | continue; |
2733 | 2747 | } |
2734 | 2748 | |
2735 | 2749 | brd->idx = m * MXSER_PORTS_PER_BOARD; |
2736 | - for (i = 0; i < brd->info->nports; i++) | |
2737 | - tty_port_register_device(&brd->ports[i].port, | |
2750 | + for (i = 0; i < brd->info->nports; i++) { | |
2751 | + tty_dev = tty_port_register_device(&brd->ports[i].port, | |
2738 | 2752 | mxvar_sdriver, brd->idx + i, NULL); |
2753 | + if (IS_ERR(tty_dev)) { | |
2754 | + for (i--; i >= 0; i--) | |
2755 | + tty_unregister_device(mxvar_sdriver, | |
2756 | + brd->idx + i); | |
2757 | + for (i = 0; i < brd->info->nports; i++) | |
2758 | + tty_port_destroy(&brd->ports[i].port); | |
2759 | + free_irq(brd->irq, brd); | |
2760 | + mxser_release_ISA_res(brd); | |
2761 | + brd->info = NULL; | |
2762 | + break; | |
2763 | + } | |
2764 | + } | |
2765 | + if (brd->info == NULL) | |
2766 | + continue; | |
2739 | 2767 | |
2740 | 2768 | m++; |
2741 | 2769 | } |