diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-03-20 08:10:47 -0400 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-05-10 04:23:19 -0400 |
commit | b19a7275dec4b470ea9abaae6129d21a0d75ab2f (patch) | |
tree | 9a3824270dee0494a198f969ae5b8c53e4950165 /drivers/pcmcia/rsrc_nonstatic.c | |
parent | 49b1153adfe18a3cce7e70aa26c690f275917cd0 (diff) |
pcmcia: clarify alloc_io_space, move it to resource handlers
Clean up the alloc_io_space() function by moving most of it to
the actual resource_ops. This allows for a bit less re-directions.
Future cleanups will follow, and will make up for the code
duplication currently present between rsrc_iodyn and rsrc_nonstatic
(which are hardly ever built at the same time anyway, therefore no
increase in built size).
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
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, |