Commit 9e17df37d710f8998e9cb10a548304fe33d4a5c2

Authored by Alexey Khoroshilov
Committed by Greg Kroah-Hartman
1 parent f30e826069

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

... ... @@ -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 }