diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2006-12-08 05:39:08 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-08 11:28:59 -0500 |
commit | 30f4218ffc5500e6a622a680f01133f9af65f07d (patch) | |
tree | 8d4fdd9dce16b7513a7a0ceb78b76921a9289f97 /drivers/char | |
parent | 39103494fd0c5325763edd06c88b121a5c21516e (diff) |
[PATCH] Char: sx, request regions
Check regions if they are free before we touch them. Release them in
failpaths.
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>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/sx.c | 55 | ||||
-rw-r--r-- | drivers/char/sx.h | 1 |
2 files changed, 50 insertions, 6 deletions
diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 1057cc4466ca..a3008ce13015 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c | |||
@@ -2497,10 +2497,13 @@ static void __devexit sx_remove_card(struct sx_board *board, | |||
2497 | 2497 | ||
2498 | /* It is safe/allowed to del_timer a non-active timer */ | 2498 | /* It is safe/allowed to del_timer a non-active timer */ |
2499 | del_timer(&board->timer); | 2499 | del_timer(&board->timer); |
2500 | if (pdev) | 2500 | if (pdev) { |
2501 | pci_iounmap(pdev, board->base); | 2501 | pci_iounmap(pdev, board->base); |
2502 | else | 2502 | pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2); |
2503 | } else { | ||
2503 | iounmap(board->base); | 2504 | iounmap(board->base); |
2505 | release_region(board->hw_base, board->hw_len); | ||
2506 | } | ||
2504 | 2507 | ||
2505 | board->flags &= ~(SX_BOARD_INITIALIZED | SX_BOARD_PRESENT); | 2508 | board->flags &= ~(SX_BOARD_INITIALIZED | SX_BOARD_PRESENT); |
2506 | } | 2509 | } |
@@ -2538,8 +2541,17 @@ static int __devinit sx_eisa_probe(struct device *dev) | |||
2538 | 2541 | ||
2539 | board->hw_base = ((inb(eisa_slot + 0xc01) << 8) + | 2542 | board->hw_base = ((inb(eisa_slot + 0xc01) << 8) + |
2540 | inb(eisa_slot + 0xc00)) << 16; | 2543 | inb(eisa_slot + 0xc00)) << 16; |
2544 | board->hw_len = SI2_EISA_WINDOW_LEN; | ||
2545 | if (!request_region(board->hw_base, board->hw_len, "sx")) { | ||
2546 | dev_err(dev, "can't request region\n"); | ||
2547 | goto err_flag; | ||
2548 | } | ||
2541 | board->base2 = | 2549 | board->base2 = |
2542 | board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN); | 2550 | board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN); |
2551 | if (!board->base) { | ||
2552 | dev_err(dev, "can't remap memory\n"); | ||
2553 | goto err_reg; | ||
2554 | } | ||
2543 | 2555 | ||
2544 | sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base); | 2556 | sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base); |
2545 | sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base); | 2557 | sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base); |
@@ -2554,6 +2566,9 @@ static int __devinit sx_eisa_probe(struct device *dev) | |||
2554 | return 0; | 2566 | return 0; |
2555 | err_unmap: | 2567 | err_unmap: |
2556 | iounmap(board->base); | 2568 | iounmap(board->base); |
2569 | err_reg: | ||
2570 | release_region(board->hw_base, board->hw_len); | ||
2571 | err_flag: | ||
2557 | board->flags &= ~SX_BOARD_PRESENT; | 2572 | board->flags &= ~SX_BOARD_PRESENT; |
2558 | err: | 2573 | err: |
2559 | return retval; | 2574 | return retval; |
@@ -2645,12 +2660,17 @@ static int __devinit sx_pci_probe(struct pci_dev *pdev, | |||
2645 | 2660 | ||
2646 | /* CF boards use base address 3.... */ | 2661 | /* CF boards use base address 3.... */ |
2647 | reg = IS_CF_BOARD(board) ? 3 : 2; | 2662 | reg = IS_CF_BOARD(board) ? 3 : 2; |
2663 | retval = pci_request_region(pdev, reg, "sx"); | ||
2664 | if (retval) { | ||
2665 | dev_err(&pdev->dev, "can't request region\n"); | ||
2666 | goto err_flag; | ||
2667 | } | ||
2648 | board->hw_base = pci_resource_start(pdev, reg); | 2668 | board->hw_base = pci_resource_start(pdev, reg); |
2649 | board->base2 = | 2669 | board->base2 = |
2650 | board->base = pci_iomap(pdev, reg, WINDOW_LEN(board)); | 2670 | board->base = pci_iomap(pdev, reg, WINDOW_LEN(board)); |
2651 | if (!board->base) { | 2671 | if (!board->base) { |
2652 | dev_err(&pdev->dev, "ioremap failed\n"); | 2672 | dev_err(&pdev->dev, "ioremap failed\n"); |
2653 | goto err_flag; | 2673 | goto err_reg; |
2654 | } | 2674 | } |
2655 | 2675 | ||
2656 | /* Most of the stuff on the CF board is offset by 0x18000 .... */ | 2676 | /* Most of the stuff on the CF board is offset by 0x18000 .... */ |
@@ -2674,6 +2694,8 @@ static int __devinit sx_pci_probe(struct pci_dev *pdev, | |||
2674 | return 0; | 2694 | return 0; |
2675 | err_unmap: | 2695 | err_unmap: |
2676 | pci_iounmap(pdev, board->base); | 2696 | pci_iounmap(pdev, board->base); |
2697 | err_reg: | ||
2698 | pci_release_region(pdev, reg); | ||
2677 | err_flag: | 2699 | err_flag: |
2678 | board->flags &= ~SX_BOARD_PRESENT; | 2700 | board->flags &= ~SX_BOARD_PRESENT; |
2679 | err: | 2701 | err: |
@@ -2736,8 +2758,13 @@ static int __init sx_init(void) | |||
2736 | for (i = 0; i < NR_SX_ADDRS; i++) { | 2758 | for (i = 0; i < NR_SX_ADDRS; i++) { |
2737 | board = &boards[found]; | 2759 | board = &boards[found]; |
2738 | board->hw_base = sx_probe_addrs[i]; | 2760 | board->hw_base = sx_probe_addrs[i]; |
2761 | board->hw_len = SX_WINDOW_LEN; | ||
2762 | if (!request_region(board->hw_base, board->hw_len, "sx")) | ||
2763 | continue; | ||
2739 | board->base2 = | 2764 | board->base2 = |
2740 | board->base = ioremap(board->hw_base, SX_WINDOW_LEN); | 2765 | board->base = ioremap(board->hw_base, board->hw_len); |
2766 | if (!board->base) | ||
2767 | goto err_sx_reg; | ||
2741 | board->flags &= ~SX_BOARD_TYPE; | 2768 | board->flags &= ~SX_BOARD_TYPE; |
2742 | board->flags |= SX_ISA_BOARD; | 2769 | board->flags |= SX_ISA_BOARD; |
2743 | board->irq = sx_irqmask ? -1 : 0; | 2770 | board->irq = sx_irqmask ? -1 : 0; |
@@ -2747,14 +2774,21 @@ static int __init sx_init(void) | |||
2747 | found++; | 2774 | found++; |
2748 | } else { | 2775 | } else { |
2749 | iounmap(board->base); | 2776 | iounmap(board->base); |
2777 | err_sx_reg: | ||
2778 | release_region(board->hw_base, board->hw_len); | ||
2750 | } | 2779 | } |
2751 | } | 2780 | } |
2752 | 2781 | ||
2753 | for (i = 0; i < NR_SI_ADDRS; i++) { | 2782 | for (i = 0; i < NR_SI_ADDRS; i++) { |
2754 | board = &boards[found]; | 2783 | board = &boards[found]; |
2755 | board->hw_base = si_probe_addrs[i]; | 2784 | board->hw_base = si_probe_addrs[i]; |
2785 | board->hw_len = SI2_ISA_WINDOW_LEN; | ||
2786 | if (!request_region(board->hw_base, board->hw_len, "sx")) | ||
2787 | continue; | ||
2756 | board->base2 = | 2788 | board->base2 = |
2757 | board->base = ioremap(board->hw_base, SI2_ISA_WINDOW_LEN); | 2789 | board->base = ioremap(board->hw_base, board->hw_len); |
2790 | if (!board->base) | ||
2791 | goto err_si_reg; | ||
2758 | board->flags &= ~SX_BOARD_TYPE; | 2792 | board->flags &= ~SX_BOARD_TYPE; |
2759 | board->flags |= SI_ISA_BOARD; | 2793 | board->flags |= SI_ISA_BOARD; |
2760 | board->irq = sx_irqmask ? -1 : 0; | 2794 | board->irq = sx_irqmask ? -1 : 0; |
@@ -2764,13 +2798,20 @@ static int __init sx_init(void) | |||
2764 | found++; | 2798 | found++; |
2765 | } else { | 2799 | } else { |
2766 | iounmap(board->base); | 2800 | iounmap(board->base); |
2801 | err_si_reg: | ||
2802 | release_region(board->hw_base, board->hw_len); | ||
2767 | } | 2803 | } |
2768 | } | 2804 | } |
2769 | for (i = 0; i < NR_SI1_ADDRS; i++) { | 2805 | for (i = 0; i < NR_SI1_ADDRS; i++) { |
2770 | board = &boards[found]; | 2806 | board = &boards[found]; |
2771 | board->hw_base = si1_probe_addrs[i]; | 2807 | board->hw_base = si1_probe_addrs[i]; |
2808 | board->hw_len = SI1_ISA_WINDOW_LEN; | ||
2809 | if (!request_region(board->hw_base, board->hw_len, "sx")) | ||
2810 | continue; | ||
2772 | board->base2 = | 2811 | board->base2 = |
2773 | board->base = ioremap(board->hw_base, SI1_ISA_WINDOW_LEN); | 2812 | board->base = ioremap(board->hw_base, board->hw_len); |
2813 | if (!board->base) | ||
2814 | goto err_si1_reg; | ||
2774 | board->flags &= ~SX_BOARD_TYPE; | 2815 | board->flags &= ~SX_BOARD_TYPE; |
2775 | board->flags |= SI1_ISA_BOARD; | 2816 | board->flags |= SI1_ISA_BOARD; |
2776 | board->irq = sx_irqmask ? -1 : 0; | 2817 | board->irq = sx_irqmask ? -1 : 0; |
@@ -2780,6 +2821,8 @@ static int __init sx_init(void) | |||
2780 | found++; | 2821 | found++; |
2781 | } else { | 2822 | } else { |
2782 | iounmap(board->base); | 2823 | iounmap(board->base); |
2824 | err_si1_reg: | ||
2825 | release_region(board->hw_base, board->hw_len); | ||
2783 | } | 2826 | } |
2784 | } | 2827 | } |
2785 | #endif | 2828 | #endif |
diff --git a/drivers/char/sx.h b/drivers/char/sx.h index e01f83cbe299..432aad0a2ddd 100644 --- a/drivers/char/sx.h +++ b/drivers/char/sx.h | |||
@@ -35,6 +35,7 @@ struct sx_board { | |||
35 | void __iomem *base; | 35 | void __iomem *base; |
36 | void __iomem *base2; | 36 | void __iomem *base2; |
37 | unsigned long hw_base; | 37 | unsigned long hw_base; |
38 | resource_size_t hw_len; | ||
38 | int eisa_base; | 39 | int eisa_base; |
39 | int port_base; /* Number of the first port */ | 40 | int port_base; /* Number of the first port */ |
40 | struct sx_port *ports; | 41 | struct sx_port *ports; |