diff options
Diffstat (limited to 'drivers/pcmcia/rsrc_nonstatic.c')
| -rw-r--r-- | drivers/pcmcia/rsrc_nonstatic.c | 105 |
1 files changed, 94 insertions, 11 deletions
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index c5ebc603b058..ba5256debde2 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c | |||
| @@ -649,8 +649,9 @@ pcmcia_align(void *align_data, const struct resource *res, | |||
| 649 | * Adjust an existing IO region allocation, but making sure that we don't | 649 | * Adjust an existing IO region allocation, but making sure that we don't |
| 650 | * encroach outside the resources which the user supplied. | 650 | * encroach outside the resources which the user supplied. |
| 651 | */ | 651 | */ |
| 652 | static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_start, | 652 | static int __nonstatic_adjust_io_region(struct pcmcia_socket *s, |
| 653 | unsigned long r_end, struct pcmcia_socket *s) | 653 | unsigned long r_start, |
| 654 | unsigned long r_end) | ||
| 654 | { | 655 | { |
| 655 | struct resource_map *m; | 656 | struct resource_map *m; |
| 656 | struct socket_data *s_data = s->resource_data; | 657 | struct socket_data *s_data = s->resource_data; |
| @@ -663,8 +664,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star | |||
| 663 | if (start > r_start || r_end > end) | 664 | if (start > r_start || r_end > end) |
| 664 | continue; | 665 | continue; |
| 665 | 666 | ||
| 666 | ret = adjust_resource(res, r_start, r_end - r_start + 1); | 667 | ret = 0; |
| 667 | break; | ||
| 668 | } | 668 | } |
| 669 | 669 | ||
| 670 | return ret; | 670 | return ret; |
| @@ -683,8 +683,9 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star | |||
| 683 | 683 | ||
| 684 | ======================================================================*/ | 684 | ======================================================================*/ |
| 685 | 685 | ||
| 686 | static struct resource *nonstatic_find_io_region(unsigned long base, int num, | 686 | static struct resource *__nonstatic_find_io_region(struct pcmcia_socket *s, |
| 687 | unsigned long align, struct pcmcia_socket *s) | 687 | unsigned long base, int num, |
| 688 | unsigned long align) | ||
| 688 | { | 689 | { |
| 689 | struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO, | 690 | struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO, |
| 690 | dev_name(&s->dev)); | 691 | dev_name(&s->dev)); |
| @@ -693,9 +694,6 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num, | |||
| 693 | unsigned long min = base; | 694 | unsigned long min = base; |
| 694 | int ret; | 695 | int ret; |
| 695 | 696 | ||
| 696 | if (align == 0) | ||
| 697 | align = 0x10000; | ||
| 698 | |||
| 699 | data.mask = align - 1; | 697 | data.mask = align - 1; |
| 700 | data.offset = base & data.mask; | 698 | data.offset = base & data.mask; |
| 701 | data.map = &s_data->io_db; | 699 | data.map = &s_data->io_db; |
| @@ -716,6 +714,92 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num, | |||
| 716 | return res; | 714 | return res; |
| 717 | } | 715 | } |
| 718 | 716 | ||
| 717 | static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr, | ||
| 718 | unsigned int *base, unsigned int num, | ||
| 719 | unsigned int align) | ||
| 720 | { | ||
| 721 | int i, ret = 0; | ||
| 722 | |||
| 723 | /* Check for an already-allocated window that must conflict with | ||
| 724 | * what was asked for. It is a hack because it does not catch all | ||
| 725 | * potential conflicts, just the most obvious ones. | ||
| 726 | */ | ||
| 727 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
| 728 | if (!s->io[i].res) | ||
| 729 | continue; | ||
| 730 | |||
| 731 | if (!*base) | ||
| 732 | continue; | ||
| 733 | |||
| 734 | if ((s->io[i].res->start & (align-1)) == *base) | ||
| 735 | return -EBUSY; | ||
| 736 | } | ||
| 737 | |||
| 738 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
| 739 | struct resource *res = s->io[i].res; | ||
| 740 | unsigned int try; | ||
| 741 | |||
| 742 | if (res && (res->flags & IORESOURCE_BITS) != | ||
| 743 | (attr & IORESOURCE_BITS)) | ||
| 744 | continue; | ||
| 745 | |||
| 746 | if (!res) { | ||
| 747 | if (align == 0) | ||
| 748 | align = 0x10000; | ||
| 749 | |||
| 750 | res = s->io[i].res = __nonstatic_find_io_region(s, | ||
| 751 | *base, num, | ||
| 752 | align); | ||
| 753 | if (!res) | ||
| 754 | return -EINVAL; | ||
| 755 | |||
| 756 | *base = res->start; | ||
| 757 | s->io[i].res->flags = | ||
| 758 | ((res->flags & ~IORESOURCE_BITS) | | ||
| 759 | (attr & IORESOURCE_BITS)); | ||
| 760 | s->io[i].InUse = num; | ||
| 761 | return 0; | ||
| 762 | } | ||
| 763 | |||
| 764 | /* Try to extend top of window */ | ||
| 765 | try = res->end + 1; | ||
| 766 | if ((*base == 0) || (*base == try)) { | ||
| 767 | ret = __nonstatic_adjust_io_region(s, res->start, | ||
| 768 | res->end + num); | ||
| 769 | if (!ret) { | ||
| 770 | ret = adjust_resource(s->io[i].res, res->start, | ||
| 771 | res->end - res->start + num + 1); | ||
| 772 | if (ret) | ||
| 773 | continue; | ||
| 774 | *base = try; | ||
| 775 | s->io[i].InUse += num; | ||
| 776 | return 0; | ||
| 777 | } | ||
| 778 | } | ||
| 779 | |||
| 780 | /* Try to extend bottom of window */ | ||
| 781 | try = res->start - num; | ||
| 782 | if ((*base == 0) || (*base == try)) { | ||
| 783 | ret = __nonstatic_adjust_io_region(s, | ||
| 784 | res->start - num, | ||
| 785 | res->end); | ||
| 786 | if (!ret) { | ||
| 787 | ret = adjust_resource(s->io[i].res, | ||
| 788 | res->start - num, | ||
| 789 | res->end - res->start + num + 1); | ||
| 790 | if (ret) | ||
| 791 | continue; | ||
| 792 | *base = try; | ||
| 793 | s->io[i].InUse += num; | ||
| 794 | return 0; | ||
| 795 | } | ||
| 796 | } | ||
| 797 | } | ||
| 798 | |||
| 799 | return -EINVAL; | ||
| 800 | } | ||
| 801 | |||
| 802 | |||
| 719 | static struct resource *nonstatic_find_mem_region(u_long base, u_long num, | 803 | static struct resource *nonstatic_find_mem_region(u_long base, u_long num, |
| 720 | u_long align, int low, struct pcmcia_socket *s) | 804 | u_long align, int low, struct pcmcia_socket *s) |
| 721 | { | 805 | { |
| @@ -946,8 +1030,7 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s) | |||
| 946 | 1030 | ||
| 947 | struct pccard_resource_ops pccard_nonstatic_ops = { | 1031 | struct pccard_resource_ops pccard_nonstatic_ops = { |
| 948 | .validate_mem = pcmcia_nonstatic_validate_mem, | 1032 | .validate_mem = pcmcia_nonstatic_validate_mem, |
| 949 | .adjust_io_region = nonstatic_adjust_io_region, | 1033 | .find_io = nonstatic_find_io, |
| 950 | .find_io = nonstatic_find_io_region, | ||
| 951 | .find_mem = nonstatic_find_mem_region, | 1034 | .find_mem = nonstatic_find_mem_region, |
| 952 | .add_io = adjust_io, | 1035 | .add_io = adjust_io, |
| 953 | .add_mem = adjust_memory, | 1036 | .add_mem = adjust_memory, |
