Lines Matching +full:num +full:- +full:ss +full:- +full:bits
1 // SPDX-License-Identifier: GPL-2.0-only
3 * rsrc_nonstatic.c -- Resource management routines for !SS_CAP_STATIC_MAP sockets
28 #include <pcmcia/ss.h>
49 u_long base, num; member
83 if (s && s->cb_dev) in claim_region()
84 parent = pci_find_parent_resource(s->cb_dev, res); in claim_region()
108 static int add_interval(struct resource_map *map, u_long base, u_long num) in add_interval() argument
112 for (p = map; ; p = p->next) { in add_interval()
113 if ((p != map) && (p->base+p->num >= base)) { in add_interval()
114 p->num = max(num + base - p->base, p->num); in add_interval()
117 if ((p->next == map) || (p->next->base > base+num-1)) in add_interval()
123 return -ENOMEM; in add_interval()
125 q->base = base; q->num = num; in add_interval()
126 q->next = p->next; p->next = q; in add_interval()
132 static int sub_interval(struct resource_map *map, u_long base, u_long num) in sub_interval() argument
137 q = p->next; in sub_interval()
140 if ((q->base+q->num > base) && (base+num > q->base)) { in sub_interval()
141 if (q->base >= base) { in sub_interval()
142 if (q->base+q->num <= base+num) { in sub_interval()
144 p->next = q->next; in sub_interval()
150 q->num = q->base + q->num - base - num; in sub_interval()
151 q->base = base + num; in sub_interval()
153 } else if (q->base+q->num <= base+num) { in sub_interval()
155 q->num = base - q->base; in sub_interval()
162 return -ENOMEM; in sub_interval()
164 p->base = base+num; in sub_interval()
165 p->num = q->base+q->num - p->base; in sub_interval()
166 q->num = base - q->base; in sub_interval()
167 p->next = q->next ; q->next = p; in sub_interval()
183 unsigned int num) in do_io_probe() argument
186 struct socket_data *s_data = s->resource_data; in do_io_probe()
191 dev_info(&s->dev, "cs: IO port probe %#x-%#x:", base, base+num-1); in do_io_probe()
197 dev_err(&s->dev, "do_io_probe: unable to kmalloc 256 bytes\n"); in do_io_probe()
200 for (i = base, most = 0; i < base+num; i += 8) { in do_io_probe()
217 for (i = base; i < base+num; i += 8) { in do_io_probe()
237 sub_interval(&s_data->io_db, bad, i-bad); in do_io_probe()
238 pr_cont(" %#x-%#x", bad, i-1); in do_io_probe()
244 if ((num > 16) && (bad == base) && (i == base+num)) { in do_io_probe()
245 sub_interval(&s_data->io_db, bad, i-bad); in do_io_probe()
249 sub_interval(&s_data->io_db, bad, i-bad); in do_io_probe()
250 pr_cont(" %#x-%#x", bad, i-1); in do_io_probe()
261 * readable() - iomem validation function for cards with a valid CIS
266 int ret = -EINVAL; in readable()
268 if (s->fake_cis) { in readable()
269 dev_dbg(&s->dev, "fake CIS is being used: can't validate mem\n"); in readable()
273 s->cis_mem.res = res; in readable()
274 s->cis_virt = ioremap(res->start, s->map_size); in readable()
275 if (s->cis_virt) { in readable()
276 mutex_unlock(&s->ops_mutex); in readable()
278 if (s->callback->validate) in readable()
279 ret = s->callback->validate(s, count); in readable()
281 mutex_lock(&s->ops_mutex); in readable()
282 iounmap(s->cis_virt); in readable()
283 s->cis_virt = NULL; in readable()
285 s->cis_mem.res = NULL; in readable()
287 return -EINVAL; in readable()
292 * checksum() - iomem validation function for simple memory cards
298 int i, a = 0, b = -1, d; in checksum()
301 virt = ioremap(res->start, s->map_size); in checksum()
308 s->ops->set_mem_map(s, &map); in checksum()
311 for (i = 0; i < s->map_size; i += 44) { in checksum()
318 s->ops->set_mem_map(s, &map); in checksum()
323 if (b == -1) in checksum()
324 return -EINVAL; in checksum()
332 * do_validate_mem() - low level validate a memory region for PCMCIA use
340 * @validate() returns non-zero, or the value parameter to @validate()
342 * the check fails, and -EINVAL is returned. Else, 0 is returned.
350 struct socket_data *s_data = s->resource_data; in do_validate_mem()
353 int ret = -EINVAL; in do_validate_mem()
367 dev_dbg(&s->dev, "cs: memory probe 0x%06lx-0x%06lx: %pr %pr %u %u %u", in do_validate_mem()
368 base, base+size-1, res1, res2, ret, info1, info2); in do_validate_mem()
374 return -EINVAL; in do_validate_mem()
376 if (validate && !s->fake_cis) { in do_validate_mem()
378 add_interval(&s_data->mem_db_valid, base, size); in do_validate_mem()
379 sub_interval(&s_data->mem_db, base, size); in do_validate_mem()
387 * do_mem_probe() - validate a memory region for PCMCIA use
390 * @num: size of resource to check
400 static int do_mem_probe(struct pcmcia_socket *s, u_long base, u_long num, in do_mem_probe() argument
408 struct socket_data *s_data = s->resource_data; in do_mem_probe()
411 dev_info(&s->dev, "cs: memory probe 0x%06lx-0x%06lx:", in do_mem_probe()
412 base, base+num-1); in do_mem_probe()
414 step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff); in do_mem_probe()
419 if (step < 2 * s->map_size) in do_mem_probe()
420 step = 2 * s->map_size; in do_mem_probe()
421 for (i = j = base; i < base+num; i = j + step) { in do_mem_probe()
423 for (j = i; j < base+num; j += step) { in do_mem_probe()
427 fail = ((i == base) && (j == base+num)); in do_mem_probe()
430 for (j = i; j < base+num; j += step) in do_mem_probe()
437 pr_cont(" %#05lx-%#05lx", i, j-1); in do_mem_probe()
438 sub_interval(&s_data->mem_db, i, j-i); in do_mem_probe()
439 bad += j-i; in do_mem_probe()
443 return num - bad; in do_mem_probe()
450 * inv_probe() - top-to-bottom search for one usuable high memory area
456 struct socket_data *s_data = s->resource_data; in inv_probe()
458 if (m == &s_data->mem_db) in inv_probe()
460 ok = inv_probe(m->next, s); in inv_probe()
462 if (m->base >= 0x100000) in inv_probe()
463 sub_interval(&s_data->mem_db, m->base, m->num); in inv_probe()
466 if (m->base < 0x100000) in inv_probe()
468 return do_mem_probe(s, m->base, m->num, readable, checksum); in inv_probe()
472 * validate_mem() - memory probe function
476 * The memory probe. If the memory list includes a 64K-aligned block
485 struct socket_data *s_data = s->resource_data; in validate_mem()
489 if (inv_probe(s_data->mem_db.next, s) > 0) in validate_mem()
491 if (s_data->mem_db_valid.next != &s_data->mem_db_valid) in validate_mem()
493 dev_notice(&s->dev, in validate_mem()
495 return -ENODEV; in validate_mem()
498 for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) { in validate_mem()
503 if ((mm.base | mm.num) & 0xffff) { in validate_mem()
504 ok += do_mem_probe(s, mm.base, mm.num, readable, in validate_mem()
508 /* Special probe for 64K-aligned block */ in validate_mem()
511 if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) { in validate_mem()
513 sub_interval(&s_data->mem_db, b, 0x10000); in validate_mem()
524 return -ENODEV; in validate_mem()
530 * validate_mem() - memory probe function
539 struct socket_data *s_data = s->resource_data; in validate_mem()
542 for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) { in validate_mem()
544 ok += do_mem_probe(s, mm.base, mm.num, readable, checksum); in validate_mem()
548 return -ENODEV; in validate_mem()
555 * pcmcia_nonstatic_validate_mem() - try to validate iomem for PCMCIA use
565 struct socket_data *s_data = s->resource_data; in pcmcia_nonstatic_validate_mem()
569 if (!probe_mem || !(s->state & SOCKET_PRESENT)) in pcmcia_nonstatic_validate_mem()
572 if (s->features & SS_CAP_PAGE_REGS) in pcmcia_nonstatic_validate_mem()
577 if (s_data->mem_db_valid.next != &s_data->mem_db_valid) in pcmcia_nonstatic_validate_mem()
596 ret = (start & ~align_data->mask) + align_data->offset; in pcmcia_common_align()
598 ret += align_data->mask + 1; in pcmcia_common_align()
610 start = pcmcia_common_align(data, res->start); in pcmcia_align()
612 for (m = data->map->next; m != data->map; m = m->next) { in pcmcia_align()
613 unsigned long map_start = m->base; in pcmcia_align()
614 unsigned long map_end = m->base + m->num - 1; in pcmcia_align()
628 if (start >= res->end) in pcmcia_align()
631 if ((start + size - 1) <= map_end) in pcmcia_align()
638 if (m == data->map) in pcmcia_align()
639 start = res->end; in pcmcia_align()
653 struct socket_data *s_data = s->resource_data; in __nonstatic_adjust_io_region()
654 int ret = -ENOMEM; in __nonstatic_adjust_io_region()
656 for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) { in __nonstatic_adjust_io_region()
657 unsigned long start = m->base; in __nonstatic_adjust_io_region()
658 unsigned long end = m->base + m->num - 1; in __nonstatic_adjust_io_region()
674 The 'align' field should reflect the number of bits of address
676 should be a power of two, greater than or equal to 'num'. A value
677 of 0 means that all bits of *base are significant. *base should
683 unsigned long base, int num, in __nonstatic_find_io_region() argument
686 struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO, in __nonstatic_find_io_region()
687 dev_name(&s->dev)); in __nonstatic_find_io_region()
688 struct socket_data *s_data = s->resource_data; in __nonstatic_find_io_region()
696 data.mask = align - 1; in __nonstatic_find_io_region()
698 data.map = &s_data->io_db; in __nonstatic_find_io_region()
701 if (s->cb_dev) { in __nonstatic_find_io_region()
702 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1, in __nonstatic_find_io_region()
706 ret = allocate_resource(&ioport_resource, res, num, min, ~0UL, in __nonstatic_find_io_region()
717 unsigned int *base, unsigned int num, in nonstatic_find_io() argument
722 /* Check for an already-allocated window that must conflict with in nonstatic_find_io()
727 if (!s->io[i].res) in nonstatic_find_io()
733 if ((s->io[i].res->start & (align-1)) == *base) in nonstatic_find_io()
734 return -EBUSY; in nonstatic_find_io()
738 struct resource *res = s->io[i].res; in nonstatic_find_io()
741 if (res && (res->flags & IORESOURCE_BITS) != in nonstatic_find_io()
749 res = s->io[i].res = __nonstatic_find_io_region(s, in nonstatic_find_io()
750 *base, num, in nonstatic_find_io()
753 return -EINVAL; in nonstatic_find_io()
755 *base = res->start; in nonstatic_find_io()
756 s->io[i].res->flags = in nonstatic_find_io()
757 ((res->flags & ~IORESOURCE_BITS) | in nonstatic_find_io()
759 s->io[i].InUse = num; in nonstatic_find_io()
765 try = res->end + 1; in nonstatic_find_io()
767 ret = __nonstatic_adjust_io_region(s, res->start, in nonstatic_find_io()
768 res->end + num); in nonstatic_find_io()
770 ret = adjust_resource(s->io[i].res, res->start, in nonstatic_find_io()
771 resource_size(res) + num); in nonstatic_find_io()
775 s->io[i].InUse += num; in nonstatic_find_io()
782 try = res->start - num; in nonstatic_find_io()
785 res->start - num, in nonstatic_find_io()
786 res->end); in nonstatic_find_io()
788 ret = adjust_resource(s->io[i].res, in nonstatic_find_io()
789 res->start - num, in nonstatic_find_io()
790 resource_size(res) + num); in nonstatic_find_io()
794 s->io[i].InUse += num; in nonstatic_find_io()
801 return -EINVAL; in nonstatic_find_io()
805 static struct resource *nonstatic_find_mem_region(u_long base, u_long num, in nonstatic_find_mem_region() argument
808 struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_MEM, in nonstatic_find_mem_region()
809 dev_name(&s->dev)); in nonstatic_find_mem_region()
810 struct socket_data *s_data = s->resource_data; in nonstatic_find_mem_region()
818 low = low || !(s->features & SS_CAP_PAGE_REGS); in nonstatic_find_mem_region()
820 data.mask = align - 1; in nonstatic_find_mem_region()
824 data.map = &s_data->mem_db_valid; in nonstatic_find_mem_region()
835 if (s->cb_dev) { in nonstatic_find_mem_region()
836 ret = pci_bus_alloc_resource(s->cb_dev->bus, in nonstatic_find_mem_region()
837 res, num, 1, min, 0, in nonstatic_find_mem_region()
843 res, num, min, max, 1, in nonstatic_find_mem_region()
848 data.map = &s_data->mem_db; in nonstatic_find_mem_region()
865 struct socket_data *data = s->resource_data; in adjust_memory()
866 unsigned long size = end - start + 1; in adjust_memory()
870 return -EINVAL; in adjust_memory()
874 ret = add_interval(&data->mem_db, start, size); in adjust_memory()
879 ret = sub_interval(&data->mem_db, start, size); in adjust_memory()
882 ret = -EINVAL; in adjust_memory()
891 struct socket_data *data = s->resource_data; in adjust_io()
902 size = end - start + 1; in adjust_io()
905 return -EINVAL; in adjust_io()
908 return -EINVAL; in adjust_io()
912 if (add_interval(&data->io_db, start, size) != 0) { in adjust_io()
913 ret = -EBUSY; in adjust_io()
922 sub_interval(&data->io_db, start, size); in adjust_io()
925 ret = -EINVAL; in adjust_io()
939 if (!s->cb_dev || !s->cb_dev->bus)
940 return -ENODEV;
951 * - Do not auto-add resources if the CardBus bridge is on
954 * - Avoid any I/O ports < 0x100.
956 * - On PCI-PCI bridges, only use resources which are set up
961 if (s->cb_dev->bus->number == 0)
962 return -EINVAL;
965 res = s->cb_dev->bus->resource[i];
967 pci_bus_for_each_resource(s->cb_dev->bus, res, i) {
972 if (res->flags & IORESOURCE_IO) {
979 dev_info(&s->cb_dev->dev,
982 if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end))
987 if (res->flags & IORESOURCE_MEM) {
994 dev_info(&s->cb_dev->dev,
997 if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end))
1005 s->resource_setup_done = 1;
1014 return -ENODEV;
1026 return -ENOMEM;
1028 data->mem_db.next = &data->mem_db;
1029 data->mem_db_valid.next = &data->mem_db_valid;
1030 data->io_db.next = &data->io_db;
1032 s->resource_data = (void *) data;
1041 struct socket_data *data = s->resource_data;
1044 for (p = data->mem_db_valid.next; p != &data->mem_db_valid; p = q) {
1045 q = p->next;
1048 for (p = data->mem_db.next; p != &data->mem_db; p = q) {
1049 q = p->next;
1052 for (p = data->io_db.next; p != &data->io_db; p = q) {
1053 q = p->next;
1079 mutex_lock(&s->ops_mutex);
1080 data = s->resource_data;
1082 for (p = data->io_db.next; p != &data->io_db; p = p->next) {
1083 if (ret > (PAGE_SIZE - 10))
1086 "0x%08lx - 0x%08lx\n",
1087 ((unsigned long) p->base),
1088 ((unsigned long) p->base + p->num - 1));
1091 mutex_unlock(&s->ops_mutex);
1104 ret = sscanf(buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
1106 ret = sscanf(buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
1109 ret = sscanf(buf, "0x%lx - 0x%lx", &start_addr,
1113 return -EINVAL;
1117 return -EINVAL;
1119 mutex_lock(&s->ops_mutex);
1121 mutex_unlock(&s->ops_mutex);
1135 mutex_lock(&s->ops_mutex);
1136 data = s->resource_data;
1138 for (p = data->mem_db_valid.next; p != &data->mem_db_valid;
1139 p = p->next) {
1140 if (ret > (PAGE_SIZE - 10))
1143 "0x%08lx - 0x%08lx\n",
1144 ((unsigned long) p->base),
1145 ((unsigned long) p->base + p->num - 1));
1148 for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
1149 if (ret > (PAGE_SIZE - 10))
1152 "0x%08lx - 0x%08lx\n",
1153 ((unsigned long) p->base),
1154 ((unsigned long) p->base + p->num - 1));
1157 mutex_unlock(&s->ops_mutex);
1170 ret = sscanf(buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
1172 ret = sscanf(buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
1175 ret = sscanf(buf, "0x%lx - 0x%lx", &start_addr,
1179 return -EINVAL;
1183 return -EINVAL;
1185 mutex_lock(&s->ops_mutex);
1187 mutex_unlock(&s->ops_mutex);
1208 if (s->resource_ops != &pccard_nonstatic_ops)
1210 return sysfs_create_group(&dev->kobj, &rsrc_attributes);
1218 if (s->resource_ops != &pccard_nonstatic_ops)
1220 sysfs_remove_group(&dev->kobj, &rsrc_attributes);