Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+204 -101
+5 -7
drivers/pcmcia/cs_internal.h
··· 52 52 53 53 struct pccard_resource_ops { 54 54 int (*validate_mem) (struct pcmcia_socket *s); 55 - int (*adjust_io_region) (struct resource *res, 56 - unsigned long r_start, 57 - unsigned long r_end, 58 - struct pcmcia_socket *s); 59 - struct resource* (*find_io) (unsigned long base, int num, 60 - unsigned long align, 61 - struct pcmcia_socket *s); 55 + int (*find_io) (struct pcmcia_socket *s, 56 + unsigned int attr, 57 + unsigned int *base, 58 + unsigned int num, 59 + unsigned int align); 62 60 struct resource* (*find_mem) (unsigned long base, unsigned long num, 63 61 unsigned long align, int low, 64 62 struct pcmcia_socket *s);
+6 -65
drivers/pcmcia/pcmcia_resource.c
··· 40 40 module_param(io_speed, int, 0444); 41 41 42 42 43 - static int pcmcia_adjust_io_region(struct resource *res, unsigned long start, 44 - unsigned long end, struct pcmcia_socket *s) 45 - { 46 - if (s->resource_ops->adjust_io_region) 47 - return s->resource_ops->adjust_io_region(res, start, end, s); 48 - return -ENOMEM; 49 - } 50 - 51 - static struct resource *pcmcia_find_io_region(unsigned long base, int num, 52 - unsigned long align, 53 - struct pcmcia_socket *s) 54 - { 55 - if (s->resource_ops->find_io) 56 - return s->resource_ops->find_io(base, num, align, s); 57 - return NULL; 58 - } 59 - 60 43 int pcmcia_validate_mem(struct pcmcia_socket *s) 61 44 { 62 45 if (s->resource_ops->validate_mem) ··· 65 82 static int alloc_io_space(struct pcmcia_socket *s, u_int attr, 66 83 unsigned int *base, unsigned int num, u_int lines) 67 84 { 68 - int i; 69 - unsigned int try, align; 85 + unsigned int align; 70 86 71 87 align = (*base) ? (lines ? 1<<lines : 0) : 1; 72 88 if (align && (align < num)) { ··· 82 100 *base, align); 83 101 align = 0; 84 102 } 85 - if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) { 86 - *base = s->io_offset | (*base & 0x0fff); 87 - return 0; 88 - } 89 - /* Check for an already-allocated window that must conflict with 90 - * what was asked for. It is a hack because it does not catch all 91 - * potential conflicts, just the most obvious ones. 92 - */ 93 - for (i = 0; i < MAX_IO_WIN; i++) 94 - if ((s->io[i].res) && *base && 95 - ((s->io[i].res->start & (align-1)) == *base)) 96 - return 1; 97 - for (i = 0; i < MAX_IO_WIN; i++) { 98 - if (!s->io[i].res) { 99 - s->io[i].res = pcmcia_find_io_region(*base, num, align, s); 100 - if (s->io[i].res) { 101 - *base = s->io[i].res->start; 102 - s->io[i].res->flags = (s->io[i].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS); 103 - s->io[i].InUse = num; 104 - break; 105 - } else 106 - return 1; 107 - } else if ((s->io[i].res->flags & IORESOURCE_BITS) != (attr & IORESOURCE_BITS)) 108 - continue; 109 - /* Try to extend top of window */ 110 - try = s->io[i].res->end + 1; 111 - if ((*base == 0) || (*base == try)) 112 - if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start, 113 - s->io[i].res->end + num, s) == 0) { 114 - *base = try; 115 - s->io[i].InUse += num; 116 - break; 117 - } 118 - /* Try to extend bottom of window */ 119 - try = s->io[i].res->start - num; 120 - if ((*base == 0) || (*base == try)) 121 - if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num, 122 - s->io[i].res->end, s) == 0) { 123 - *base = try; 124 - s->io[i].InUse += num; 125 - break; 126 - } 127 - } 128 - return (i == MAX_IO_WIN); 103 + 104 + return s->resource_ops->find_io(s, attr, base, num, align); 129 105 } /* alloc_io_space */ 130 106 131 107 ··· 623 683 * free_irq themselves, too), or the pcmcia_request_irq() function. 624 684 */ 625 685 int __must_check 626 - pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev, irq_handler_t handler) 686 + __pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev, 687 + irq_handler_t handler) 627 688 { 628 689 int ret; 629 690 ··· 646 705 647 706 return ret; 648 707 } /* pcmcia_request_exclusive_irq */ 649 - EXPORT_SYMBOL(pcmcia_request_exclusive_irq); 708 + EXPORT_SYMBOL(__pcmcia_request_exclusive_irq); 650 709 651 710 652 711 #ifdef CONFIG_PCMCIA_PROBE
+78 -14
drivers/pcmcia/rsrc_iodyn.c
··· 56 56 } 57 57 58 58 59 - static int iodyn_adjust_io_region(struct resource *res, unsigned long r_start, 60 - unsigned long r_end, struct pcmcia_socket *s) 61 - { 62 - return adjust_resource(res, r_start, r_end - r_start + 1); 63 - } 64 - 65 - 66 - static struct resource *iodyn_find_io_region(unsigned long base, int num, 67 - unsigned long align, struct pcmcia_socket *s) 59 + static struct resource *__iodyn_find_io_region(struct pcmcia_socket *s, 60 + unsigned long base, int num, 61 + unsigned long align) 68 62 { 69 63 struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO, 70 64 dev_name(&s->dev)); 71 65 struct pcmcia_align_data data; 72 66 unsigned long min = base; 73 67 int ret; 74 - 75 - if (align == 0) 76 - align = 0x10000; 77 68 78 69 data.mask = align - 1; 79 70 data.offset = base & data.mask; ··· 85 94 return res; 86 95 } 87 96 97 + static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr, 98 + unsigned int *base, unsigned int num, 99 + unsigned int align) 100 + { 101 + int i, ret = 0; 102 + 103 + /* Check for an already-allocated window that must conflict with 104 + * what was asked for. It is a hack because it does not catch all 105 + * potential conflicts, just the most obvious ones. 106 + */ 107 + for (i = 0; i < MAX_IO_WIN; i++) { 108 + if (!s->io[i].res) 109 + continue; 110 + 111 + if (!*base) 112 + continue; 113 + 114 + if ((s->io[i].res->start & (align-1)) == *base) 115 + return -EBUSY; 116 + } 117 + 118 + for (i = 0; i < MAX_IO_WIN; i++) { 119 + struct resource *res = s->io[i].res; 120 + unsigned int try; 121 + 122 + if (res && (res->flags & IORESOURCE_BITS) != 123 + (attr & IORESOURCE_BITS)) 124 + continue; 125 + 126 + if (!res) { 127 + if (align == 0) 128 + align = 0x10000; 129 + 130 + res = s->io[i].res = __iodyn_find_io_region(s, *base, 131 + num, align); 132 + if (!res) 133 + return -EINVAL; 134 + 135 + *base = res->start; 136 + s->io[i].res->flags = 137 + ((res->flags & ~IORESOURCE_BITS) | 138 + (attr & IORESOURCE_BITS)); 139 + s->io[i].InUse = num; 140 + return 0; 141 + } 142 + 143 + /* Try to extend top of window */ 144 + try = res->end + 1; 145 + if ((*base == 0) || (*base == try)) { 146 + if (adjust_resource(s->io[i].res, res->start, 147 + res->end - res->start + num + 1)) 148 + continue; 149 + *base = try; 150 + s->io[i].InUse += num; 151 + return 0; 152 + } 153 + 154 + /* Try to extend bottom of window */ 155 + try = res->start - num; 156 + if ((*base == 0) || (*base == try)) { 157 + if (adjust_resource(s->io[i].res, 158 + res->start - num, 159 + res->end - res->start + num + 1)) 160 + continue; 161 + *base = try; 162 + s->io[i].InUse += num; 163 + return 0; 164 + } 165 + } 166 + 167 + return -EINVAL; 168 + } 169 + 170 + 88 171 struct pccard_resource_ops pccard_iodyn_ops = { 89 172 .validate_mem = NULL, 90 - .adjust_io_region = iodyn_adjust_io_region, 91 - .find_io = iodyn_find_io_region, 173 + .find_io = iodyn_find_io, 92 174 .find_mem = NULL, 93 175 .add_io = NULL, 94 176 .add_mem = NULL,
+12 -2
drivers/pcmcia/rsrc_mgr.c
··· 46 46 return res; 47 47 } 48 48 49 + static int static_find_io(struct pcmcia_socket *s, unsigned int attr, 50 + unsigned int *base, unsigned int num, 51 + unsigned int align) 52 + { 53 + if (!s->io_offset) 54 + return -EINVAL; 55 + *base = s->io_offset | (*base & 0x0fff); 56 + 57 + return 0; 58 + } 59 + 49 60 50 61 struct pccard_resource_ops pccard_static_ops = { 51 62 .validate_mem = NULL, 52 - .adjust_io_region = NULL, 53 - .find_io = NULL, 63 + .find_io = static_find_io, 54 64 .find_mem = NULL, 55 65 .add_io = NULL, 56 66 .add_mem = NULL,
+94 -11
drivers/pcmcia/rsrc_nonstatic.c
··· 649 649 * Adjust an existing IO region allocation, but making sure that we don't 650 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, 653 - unsigned long r_end, struct pcmcia_socket *s) 652 + static int __nonstatic_adjust_io_region(struct pcmcia_socket *s, 653 + unsigned long r_start, 654 + unsigned long r_end) 654 655 { 655 656 struct resource_map *m; 656 657 struct socket_data *s_data = s->resource_data; ··· 664 663 if (start > r_start || r_end > end) 665 664 continue; 666 665 667 - ret = adjust_resource(res, r_start, r_end - r_start + 1); 668 - break; 666 + ret = 0; 669 667 } 670 668 671 669 return ret; ··· 683 683 684 684 ======================================================================*/ 685 685 686 - static struct resource *nonstatic_find_io_region(unsigned long base, int num, 687 - unsigned long align, struct pcmcia_socket *s) 686 + static struct resource *__nonstatic_find_io_region(struct pcmcia_socket *s, 687 + unsigned long base, int num, 688 + unsigned long align) 688 689 { 689 690 struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO, 690 691 dev_name(&s->dev)); ··· 693 692 struct pcmcia_align_data data; 694 693 unsigned long min = base; 695 694 int ret; 696 - 697 - if (align == 0) 698 - align = 0x10000; 699 695 700 696 data.mask = align - 1; 701 697 data.offset = base & data.mask; ··· 713 715 } 714 716 return res; 715 717 } 718 + 719 + static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr, 720 + unsigned int *base, unsigned int num, 721 + unsigned int align) 722 + { 723 + int i, ret = 0; 724 + 725 + /* Check for an already-allocated window that must conflict with 726 + * what was asked for. It is a hack because it does not catch all 727 + * potential conflicts, just the most obvious ones. 728 + */ 729 + for (i = 0; i < MAX_IO_WIN; i++) { 730 + if (!s->io[i].res) 731 + continue; 732 + 733 + if (!*base) 734 + continue; 735 + 736 + if ((s->io[i].res->start & (align-1)) == *base) 737 + return -EBUSY; 738 + } 739 + 740 + for (i = 0; i < MAX_IO_WIN; i++) { 741 + struct resource *res = s->io[i].res; 742 + unsigned int try; 743 + 744 + if (res && (res->flags & IORESOURCE_BITS) != 745 + (attr & IORESOURCE_BITS)) 746 + continue; 747 + 748 + if (!res) { 749 + if (align == 0) 750 + align = 0x10000; 751 + 752 + res = s->io[i].res = __nonstatic_find_io_region(s, 753 + *base, num, 754 + align); 755 + if (!res) 756 + return -EINVAL; 757 + 758 + *base = res->start; 759 + s->io[i].res->flags = 760 + ((res->flags & ~IORESOURCE_BITS) | 761 + (attr & IORESOURCE_BITS)); 762 + s->io[i].InUse = num; 763 + return 0; 764 + } 765 + 766 + /* Try to extend top of window */ 767 + try = res->end + 1; 768 + if ((*base == 0) || (*base == try)) { 769 + ret = __nonstatic_adjust_io_region(s, res->start, 770 + res->end + num); 771 + if (!ret) { 772 + ret = adjust_resource(s->io[i].res, res->start, 773 + res->end - res->start + num + 1); 774 + if (ret) 775 + continue; 776 + *base = try; 777 + s->io[i].InUse += num; 778 + return 0; 779 + } 780 + } 781 + 782 + /* Try to extend bottom of window */ 783 + try = res->start - num; 784 + if ((*base == 0) || (*base == try)) { 785 + ret = __nonstatic_adjust_io_region(s, 786 + res->start - num, 787 + res->end); 788 + if (!ret) { 789 + ret = adjust_resource(s->io[i].res, 790 + res->start - num, 791 + res->end - res->start + num + 1); 792 + if (ret) 793 + continue; 794 + *base = try; 795 + s->io[i].InUse += num; 796 + return 0; 797 + } 798 + } 799 + } 800 + 801 + return -EINVAL; 802 + } 803 + 716 804 717 805 static struct resource *nonstatic_find_mem_region(u_long base, u_long num, 718 806 u_long align, int low, struct pcmcia_socket *s) ··· 1030 946 1031 947 struct pccard_resource_ops pccard_nonstatic_ops = { 1032 948 .validate_mem = pcmcia_nonstatic_validate_mem, 1033 - .adjust_io_region = nonstatic_adjust_io_region, 1034 - .find_io = nonstatic_find_io_region, 949 + .find_io = nonstatic_find_io, 1035 950 .find_mem = nonstatic_find_mem_region, 1036 951 .add_io = adjust_io, 1037 952 .add_mem = adjust_memory,
+9 -2
include/pcmcia/ds.h
··· 184 184 /* device configuration */ 185 185 int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req); 186 186 187 - int __must_check __deprecated 188 - pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev, 187 + int __must_check 188 + __pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev, 189 189 irq_handler_t handler); 190 + static inline __must_check __deprecated int 191 + pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev, 192 + irq_handler_t handler) 193 + { 194 + return __pcmcia_request_exclusive_irq(p_dev, handler); 195 + } 196 + 190 197 int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev, 191 198 irq_handler_t handler); 192 199