]> nv-tegra.nvidia Code Review - linux-3.10.git/blob - drivers/pcmcia/rsrc_nonstatic.c
[PATCH] pcmcia: resource handling fixes
[linux-3.10.git] / drivers / pcmcia / rsrc_nonstatic.c
1 /*
2  * rsrc_nonstatic.c -- Resource management routines for !SS_CAP_STATIC_MAP sockets
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * The initial developer of the original code is David A. Hinds
9  * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
10  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
11  *
12  * (C) 1999             David A. Hinds
13  */
14
15 #include <linux/config.h>
16 #include <linux/module.h>
17 #include <linux/moduleparam.h>
18 #include <linux/init.h>
19 #include <linux/interrupt.h>
20 #include <linux/kernel.h>
21 #include <linux/errno.h>
22 #include <linux/types.h>
23 #include <linux/slab.h>
24 #include <linux/ioport.h>
25 #include <linux/timer.h>
26 #include <linux/pci.h>
27 #include <linux/device.h>
28
29 #include <asm/irq.h>
30 #include <asm/io.h>
31
32 #include <pcmcia/cs_types.h>
33 #include <pcmcia/ss.h>
34 #include <pcmcia/cs.h>
35 #include <pcmcia/bulkmem.h>
36 #include <pcmcia/cistpl.h>
37 #include "cs_internal.h"
38
39 MODULE_AUTHOR("David A. Hinds, Dominik Brodowski");
40 MODULE_LICENSE("GPL");
41
42 /* Parameters that can be set with 'insmod' */
43
44 #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
45
46 INT_MODULE_PARM(probe_mem,      1);             /* memory probe? */
47 #ifdef CONFIG_PCMCIA_PROBE
48 INT_MODULE_PARM(probe_io,       1);             /* IO port probe? */
49 INT_MODULE_PARM(mem_limit,      0x10000);
50 #endif
51
52 /* for io_db and mem_db */
53 struct resource_map {
54         u_long                  base, num;
55         struct resource_map     *next;
56 };
57
58 struct socket_data {
59         struct resource_map             mem_db;
60         struct resource_map             io_db;
61         unsigned int                    rsrc_mem_probe;
62 };
63
64 static DECLARE_MUTEX(rsrc_sem);
65 #define MEM_PROBE_LOW   (1 << 0)
66 #define MEM_PROBE_HIGH  (1 << 1)
67
68
69 /*======================================================================
70
71     Linux resource management extensions
72
73 ======================================================================*/
74
75 static struct resource *
76 make_resource(unsigned long b, unsigned long n, int flags, char *name)
77 {
78         struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
79
80         if (res) {
81                 memset(res, 0, sizeof(*res));
82                 res->name = name;
83                 res->start = b;
84                 res->end = b + n - 1;
85                 res->flags = flags;
86         }
87         return res;
88 }
89
90 static struct resource *
91 claim_region(struct pcmcia_socket *s, unsigned long base, unsigned long size,
92              int type, char *name)
93 {
94         struct resource *res, *parent;
95
96         parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource;
97         res = make_resource(base, size, type | IORESOURCE_BUSY, name);
98
99         if (res) {
100 #ifdef CONFIG_PCI
101                 if (s && s->cb_dev)
102                         parent = pci_find_parent_resource(s->cb_dev, res);
103 #endif
104                 if (!parent || request_resource(parent, res)) {
105                         kfree(res);
106                         res = NULL;
107                 }
108         }
109         return res;
110 }
111
112 static void free_region(struct resource *res)
113 {
114         if (res) {
115                 release_resource(res);
116                 kfree(res);
117         }
118 }
119
120 /*======================================================================
121
122     These manage the internal databases of available resources.
123
124 ======================================================================*/
125
126 static int add_interval(struct resource_map *map, u_long base, u_long num)
127 {
128     struct resource_map *p, *q;
129
130     for (p = map; ; p = p->next) {
131         if ((p != map) && (p->base+p->num-1 >= base))
132             return -1;
133         if ((p->next == map) || (p->next->base > base+num-1))
134             break;
135     }
136     q = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
137     if (!q) return CS_OUT_OF_RESOURCE;
138     q->base = base; q->num = num;
139     q->next = p->next; p->next = q;
140     return CS_SUCCESS;
141 }
142
143 /*====================================================================*/
144
145 static int sub_interval(struct resource_map *map, u_long base, u_long num)
146 {
147     struct resource_map *p, *q;
148
149     for (p = map; ; p = q) {
150         q = p->next;
151         if (q == map)
152             break;
153         if ((q->base+q->num > base) && (base+num > q->base)) {
154             if (q->base >= base) {
155                 if (q->base+q->num <= base+num) {
156                     /* Delete whole block */
157                     p->next = q->next;
158                     kfree(q);
159                     /* don't advance the pointer yet */
160                     q = p;
161                 } else {
162                     /* Cut off bit from the front */
163                     q->num = q->base + q->num - base - num;
164                     q->base = base + num;
165                 }
166             } else if (q->base+q->num <= base+num) {
167                 /* Cut off bit from the end */
168                 q->num = base - q->base;
169             } else {
170                 /* Split the block into two pieces */
171                 p = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
172                 if (!p) return CS_OUT_OF_RESOURCE;
173                 p->base = base+num;
174                 p->num = q->base+q->num - p->base;
175                 q->num = base - q->base;
176                 p->next = q->next ; q->next = p;
177             }
178         }
179     }
180     return CS_SUCCESS;
181 }
182
183 /*======================================================================
184
185     These routines examine a region of IO or memory addresses to
186     determine what ranges might be genuinely available.
187
188 ======================================================================*/
189
190 #ifdef CONFIG_PCMCIA_PROBE
191 static void do_io_probe(struct pcmcia_socket *s, kio_addr_t base, kio_addr_t num)
192 {
193     struct resource *res;
194     struct socket_data *s_data = s->resource_data;
195     kio_addr_t i, j, bad;
196     int any;
197     u_char *b, hole, most;
198
199     printk(KERN_INFO "cs: IO port probe %#lx-%#lx:",
200            base, base+num-1);
201
202     /* First, what does a floating port look like? */
203     b = kmalloc(256, GFP_KERNEL);
204     if (!b) {
205             printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
206             return;
207     }
208     memset(b, 0, 256);
209     for (i = base, most = 0; i < base+num; i += 8) {
210         res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
211         if (!res)
212             continue;
213         hole = inb(i);
214         for (j = 1; j < 8; j++)
215             if (inb(i+j) != hole) break;
216         free_region(res);
217         if ((j == 8) && (++b[hole] > b[most]))
218             most = hole;
219         if (b[most] == 127) break;
220     }
221     kfree(b);
222
223     bad = any = 0;
224     for (i = base; i < base+num; i += 8) {
225         res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
226         if (!res)
227             continue;
228         for (j = 0; j < 8; j++)
229             if (inb(i+j) != most) break;
230         free_region(res);
231         if (j < 8) {
232             if (!any)
233                 printk(" excluding");
234             if (!bad)
235                 bad = any = i;
236         } else {
237             if (bad) {
238                 sub_interval(&s_data->io_db, bad, i-bad);
239                 printk(" %#lx-%#lx", bad, i-1);
240                 bad = 0;
241             }
242         }
243     }
244     if (bad) {
245         if ((num > 16) && (bad == base) && (i == base+num)) {
246             printk(" nothing: probe failed.\n");
247             return;
248         } else {
249             sub_interval(&s_data->io_db, bad, i-bad);
250             printk(" %#lx-%#lx", bad, i-1);
251         }
252     }
253
254     printk(any ? "\n" : " clean.\n");
255 }
256 #endif
257
258 /*======================================================================
259
260     This is tricky... when we set up CIS memory, we try to validate
261     the memory window space allocations.
262
263 ======================================================================*/
264
265 /* Validation function for cards with a valid CIS */
266 static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *info)
267 {
268         int ret = -1;
269
270         s->cis_mem.res = res;
271         s->cis_virt = ioremap(res->start, s->map_size);
272         if (s->cis_virt) {
273                 ret = pccard_validate_cis(s, BIND_FN_ALL, info);
274                 /* invalidate mapping and CIS cache */
275                 iounmap(s->cis_virt);
276                 s->cis_virt = NULL;
277                 destroy_cis_cache(s);
278         }
279         s->cis_mem.res = NULL;
280         if ((ret != 0) || (info->Chains == 0))
281                 return 0;
282         return 1;
283 }
284
285 /* Validation function for simple memory cards */
286 static int checksum(struct pcmcia_socket *s, struct resource *res)
287 {
288         pccard_mem_map map;
289         int i, a = 0, b = -1, d;
290         void __iomem *virt;
291
292         virt = ioremap(res->start, s->map_size);
293         if (virt) {
294                 map.map = 0;
295                 map.flags = MAP_ACTIVE;
296                 map.speed = 0;
297                 map.res = res;
298                 map.card_start = 0;
299                 s->ops->set_mem_map(s, &map);
300
301                 /* Don't bother checking every word... */
302                 for (i = 0; i < s->map_size; i += 44) {
303                         d = readl(virt+i);
304                         a += d;
305                         b &= d;
306                 }
307
308                 map.flags = 0;
309                 s->ops->set_mem_map(s, &map);
310
311                 iounmap(virt);
312         }
313
314         return (b == -1) ? -1 : (a>>1);
315 }
316
317 static int
318 cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
319 {
320         struct resource *res1, *res2;
321         cisinfo_t info1, info2;
322         int ret = 0;
323
324         res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
325         res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
326
327         if (res1 && res2) {
328                 ret = readable(s, res1, &info1);
329                 ret += readable(s, res2, &info2);
330         }
331
332         free_region(res2);
333         free_region(res1);
334
335         return (ret == 2) && (info1.Chains == info2.Chains);
336 }
337
338 static int
339 checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size)
340 {
341         struct resource *res1, *res2;
342         int a = -1, b = -1;
343
344         res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
345         res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
346
347         if (res1 && res2) {
348                 a = checksum(s, res1);
349                 b = checksum(s, res2);
350         }
351
352         free_region(res2);
353         free_region(res1);
354
355         return (a == b) && (a >= 0);
356 }
357
358 /*======================================================================
359
360     The memory probe.  If the memory list includes a 64K-aligned block
361     below 1MB, we probe in 64K chunks, and as soon as we accumulate at
362     least mem_limit free space, we quit.
363
364 ======================================================================*/
365
366 static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
367 {
368     struct socket_data *s_data = s->resource_data;
369     u_long i, j, bad, fail, step;
370
371     printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:",
372            base, base+num-1);
373     bad = fail = 0;
374     step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
375     /* don't allow too large steps */
376     if (step > 0x800000)
377         step = 0x800000;
378     /* cis_readable wants to map 2x map_size */
379     if (step < 2 * s->map_size)
380         step = 2 * s->map_size;
381     for (i = j = base; i < base+num; i = j + step) {
382         if (!fail) {
383             for (j = i; j < base+num; j += step) {
384                 if (cis_readable(s, j, step))
385                     break;
386             }
387             fail = ((i == base) && (j == base+num));
388         }
389         if (fail) {
390             for (j = i; j < base+num; j += 2*step)
391                 if (checksum_match(s, j, step) &&
392                     checksum_match(s, j + step, step))
393                     break;
394         }
395         if (i != j) {
396             if (!bad) printk(" excluding");
397             printk(" %#05lx-%#05lx", i, j-1);
398             sub_interval(&s_data->mem_db, i, j-i);
399             bad += j-i;
400         }
401     }
402     printk(bad ? "\n" : " clean.\n");
403     return (num - bad);
404 }
405
406 #ifdef CONFIG_PCMCIA_PROBE
407
408 static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
409 {
410     struct socket_data *s_data = s->resource_data;
411     u_long ok;
412     if (m == &s_data->mem_db)
413         return 0;
414     ok = inv_probe(m->next, s);
415     if (ok) {
416         if (m->base >= 0x100000)
417             sub_interval(&s_data->mem_db, m->base, m->num);
418         return ok;
419     }
420     if (m->base < 0x100000)
421         return 0;
422     return do_mem_probe(m->base, m->num, s);
423 }
424
425 static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
426 {
427     struct resource_map *m, mm;
428     static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
429     u_long b, i, ok = 0;
430     struct socket_data *s_data = s->resource_data;
431
432     /* We do up to four passes through the list */
433     if (probe_mask & MEM_PROBE_HIGH) {
434         if (inv_probe(s_data->mem_db.next, s) > 0)
435             return;
436         printk(KERN_NOTICE "cs: warning: no high memory space "
437                "available!\n");
438     }
439     if ((probe_mask & MEM_PROBE_LOW) == 0)
440         return;
441     for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
442         mm = *m;
443         /* Only probe < 1 MB */
444         if (mm.base >= 0x100000) continue;
445         if ((mm.base | mm.num) & 0xffff) {
446             ok += do_mem_probe(mm.base, mm.num, s);
447             continue;
448         }
449         /* Special probe for 64K-aligned block */
450         for (i = 0; i < 4; i++) {
451             b = order[i] << 12;
452             if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
453                 if (ok >= mem_limit)
454                     sub_interval(&s_data->mem_db, b, 0x10000);
455                 else
456                     ok += do_mem_probe(b, 0x10000, s);
457             }
458         }
459     }
460 }
461
462 #else /* CONFIG_PCMCIA_PROBE */
463
464 static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
465 {
466         struct resource_map *m, mm;
467         struct socket_data *s_data = s->resource_data;
468
469         for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
470                 mm = *m;
471                 do_mem_probe(mm.base, mm.num, s);
472         }
473 }
474
475 #endif /* CONFIG_PCMCIA_PROBE */
476
477
478 /*
479  * Locking note: Must be called with skt_sem held!
480  */
481 static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
482 {
483         struct socket_data *s_data = s->resource_data;
484         if (probe_mem) {
485                 unsigned int probe_mask;
486
487                 down(&rsrc_sem);
488
489                 probe_mask = MEM_PROBE_LOW;
490                 if (s->features & SS_CAP_PAGE_REGS)
491                         probe_mask = MEM_PROBE_HIGH;
492
493                 if (probe_mask & ~s_data->rsrc_mem_probe) {
494                         s_data->rsrc_mem_probe |= probe_mask;
495
496                         if (s->state & SOCKET_PRESENT)
497                                 validate_mem(s, probe_mask);
498                 }
499
500                 up(&rsrc_sem);
501         }
502 }
503
504 struct pcmcia_align_data {
505         unsigned long   mask;
506         unsigned long   offset;
507         struct resource_map     *map;
508 };
509
510 static void
511 pcmcia_common_align(void *align_data, struct resource *res,
512                     unsigned long size, unsigned long align)
513 {
514         struct pcmcia_align_data *data = align_data;
515         unsigned long start;
516         /*
517          * Ensure that we have the correct start address
518          */
519         start = (res->start & ~data->mask) + data->offset;
520         if (start < res->start)
521                 start += data->mask + 1;
522         res->start = start;
523 }
524
525 static void
526 pcmcia_align(void *align_data, struct resource *res,
527              unsigned long size, unsigned long align)
528 {
529         struct pcmcia_align_data *data = align_data;
530         struct resource_map *m;
531
532         pcmcia_common_align(data, res, size, align);
533
534         for (m = data->map->next; m != data->map; m = m->next) {
535                 unsigned long start = m->base;
536                 unsigned long end = m->base + m->num - 1;
537
538                 /*
539                  * If the lower resources are not available, try aligning
540                  * to this entry of the resource database to see if it'll
541                  * fit here.
542                  */
543                 if (res->start < start) {
544                         res->start = start;
545                         pcmcia_common_align(data, res, size, align);
546                 }
547
548                 /*
549                  * If we're above the area which was passed in, there's
550                  * no point proceeding.
551                  */
552                 if (res->start >= res->end)
553                         break;
554
555                 if ((res->start + size - 1) <= end)
556                         break;
557         }
558
559         /*
560          * If we failed to find something suitable, ensure we fail.
561          */
562         if (m == data->map)
563                 res->start = res->end;
564 }
565
566 /*
567  * Adjust an existing IO region allocation, but making sure that we don't
568  * encroach outside the resources which the user supplied.
569  */
570 static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_start,
571                                       unsigned long r_end, struct pcmcia_socket *s)
572 {
573         struct resource_map *m;
574         struct socket_data *s_data = s->resource_data;
575         int ret = -ENOMEM;
576
577         down(&rsrc_sem);
578         for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) {
579                 unsigned long start = m->base;
580                 unsigned long end = m->base + m->num - 1;
581
582                 if (start > r_start || r_end > end)
583                         continue;
584
585                 ret = adjust_resource(res, r_start, r_end - r_start + 1);
586                 break;
587         }
588         up(&rsrc_sem);
589
590         return ret;
591 }
592
593 /*======================================================================
594
595     These find ranges of I/O ports or memory addresses that are not
596     currently allocated by other devices.
597
598     The 'align' field should reflect the number of bits of address
599     that need to be preserved from the initial value of *base.  It
600     should be a power of two, greater than or equal to 'num'.  A value
601     of 0 means that all bits of *base are significant.  *base should
602     also be strictly less than 'align'.
603
604 ======================================================================*/
605
606 static struct resource *nonstatic_find_io_region(unsigned long base, int num,
607                    unsigned long align, struct pcmcia_socket *s)
608 {
609         struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id);
610         struct socket_data *s_data = s->resource_data;
611         struct pcmcia_align_data data;
612         unsigned long min = base;
613         int ret;
614
615         if (align == 0)
616                 align = 0x10000;
617
618         data.mask = align - 1;
619         data.offset = base & data.mask;
620         data.map = &s_data->io_db;
621
622         down(&rsrc_sem);
623 #ifdef CONFIG_PCI
624         if (s->cb_dev) {
625                 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
626                                              min, 0, pcmcia_align, &data);
627         } else
628 #endif
629                 ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
630                                         1, pcmcia_align, &data);
631         up(&rsrc_sem);
632
633         if (ret != 0) {
634                 kfree(res);
635                 res = NULL;
636         }
637         return res;
638 }
639
640 static struct resource * nonstatic_find_mem_region(u_long base, u_long num,
641                 u_long align, int low, struct pcmcia_socket *s)
642 {
643         struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id);
644         struct socket_data *s_data = s->resource_data;
645         struct pcmcia_align_data data;
646         unsigned long min, max;
647         int ret, i;
648
649         low = low || !(s->features & SS_CAP_PAGE_REGS);
650
651         data.mask = align - 1;
652         data.offset = base & data.mask;
653         data.map = &s_data->mem_db;
654
655         for (i = 0; i < 2; i++) {
656                 if (low) {
657                         max = 0x100000UL;
658                         min = base < max ? base : 0;
659                 } else {
660                         max = ~0UL;
661                         min = 0x100000UL + base;
662                 }
663
664                 down(&rsrc_sem);
665 #ifdef CONFIG_PCI
666                 if (s->cb_dev) {
667                         ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
668                                                      1, min, 0,
669                                                      pcmcia_align, &data);
670                 } else
671 #endif
672                         ret = allocate_resource(&iomem_resource, res, num, min,
673                                                 max, 1, pcmcia_align, &data);
674                 up(&rsrc_sem);
675                 if (ret == 0 || low)
676                         break;
677                 low = 1;
678         }
679
680         if (ret != 0) {
681                 kfree(res);
682                 res = NULL;
683         }
684         return res;
685 }
686
687
688 static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
689 {
690         struct socket_data *data = s->resource_data;
691         unsigned long size = end - start + 1;
692         int ret = 0;
693
694         if (end <= start)
695                 return -EINVAL;
696
697         down(&rsrc_sem);
698         switch (action) {
699         case ADD_MANAGED_RESOURCE:
700                 ret = add_interval(&data->mem_db, start, size);
701                 break;
702         case REMOVE_MANAGED_RESOURCE:
703                 ret = sub_interval(&data->mem_db, start, size);
704                 if (!ret) {
705                         struct pcmcia_socket *socket;
706                         down_read(&pcmcia_socket_list_rwsem);
707                         list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
708                                 release_cis_mem(socket);
709                         up_read(&pcmcia_socket_list_rwsem);
710                 }
711                 break;
712         default:
713                 ret = -EINVAL;
714         }
715         up(&rsrc_sem);
716
717         return ret;
718 }
719
720
721 static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
722 {
723         struct socket_data *data = s->resource_data;
724         unsigned long size = end - start + 1;
725         int ret = 0;
726
727         if (end <= start)
728                 return -EINVAL;
729
730         if (end > IO_SPACE_LIMIT)
731                 return -EINVAL;
732
733         down(&rsrc_sem);
734         switch (action) {
735         case ADD_MANAGED_RESOURCE:
736                 if (add_interval(&data->io_db, start, size) != 0) {
737                         ret = -EBUSY;
738                         break;
739                 }
740 #ifdef CONFIG_PCMCIA_PROBE
741                 if (probe_io)
742                         do_io_probe(s, start, size);
743 #endif
744                 break;
745         case REMOVE_MANAGED_RESOURCE:
746                 sub_interval(&data->io_db, start, size);
747                 break;
748         default:
749                 ret = -EINVAL;
750                 break;
751         }
752         up(&rsrc_sem);
753
754         return ret;
755 }
756
757
758 static int nonstatic_adjust_resource_info(struct pcmcia_socket *s, adjust_t *adj)
759 {
760         unsigned long end;
761
762         switch (adj->Resource) {
763         case RES_MEMORY_RANGE:
764                 end = adj->resource.memory.Base + adj->resource.memory.Size - 1;
765                 return adjust_memory(s, adj->Action, adj->resource.memory.Base, end);
766         case RES_IO_RANGE:
767                 end = adj->resource.io.BasePort + adj->resource.io.NumPorts - 1;
768                 return adjust_io(s, adj->Action, adj->resource.io.BasePort, end);
769         }
770         return CS_UNSUPPORTED_FUNCTION;
771 }
772
773 #ifdef CONFIG_PCI
774 static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
775 {
776         struct resource *res;
777         int i, done = 0;
778
779         if (!s->cb_dev || !s->cb_dev->bus)
780                 return -ENODEV;
781
782         for (i=0; i < PCI_BUS_NUM_RESOURCES; i++) {
783                 res = s->cb_dev->bus->resource[i];
784                 if (!res)
785                         continue;
786
787                 if (res->flags & IORESOURCE_IO) {
788                         if (res == &ioport_resource)
789                                 continue;
790                         printk(KERN_INFO "pcmcia: parent PCI bridge I/O window: 0x%lx - 0x%lx\n",
791                                res->start, res->end);
792                         if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end))
793                                 done |= IORESOURCE_IO;
794
795                 }
796
797                 if (res->flags & IORESOURCE_MEM) {
798                         if (res == &iomem_resource)
799                                 continue;
800                         printk(KERN_INFO "pcmcia: parent PCI bridge Memory window: 0x%lx - 0x%lx\n",
801                                res->start, res->end);
802                         if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end))
803                                 done |= IORESOURCE_MEM;
804                 }
805         }
806
807         /* if we got at least one of IO, and one of MEM, we can be glad and
808          * activate the PCMCIA subsystem */
809         if (done & (IORESOURCE_MEM | IORESOURCE_IO))
810                 s->resource_setup_done = 1;
811
812         return 0;
813 }
814
815 #else
816
817 static inline int nonstatic_autoadd_resources(struct pcmcia_socket *s)
818 {
819         return -ENODEV;
820 }
821
822 #endif
823
824
825 static int nonstatic_init(struct pcmcia_socket *s)
826 {
827         struct socket_data *data;
828
829         data = kmalloc(sizeof(struct socket_data), GFP_KERNEL);
830         if (!data)
831                 return -ENOMEM;
832         memset(data, 0, sizeof(struct socket_data));
833
834         data->mem_db.next = &data->mem_db;
835         data->io_db.next = &data->io_db;
836
837         s->resource_data = (void *) data;
838
839         nonstatic_autoadd_resources(s);
840
841         return 0;
842 }
843
844 static void nonstatic_release_resource_db(struct pcmcia_socket *s)
845 {
846         struct socket_data *data = s->resource_data;
847         struct resource_map *p, *q;
848
849         down(&rsrc_sem);
850         for (p = data->mem_db.next; p != &data->mem_db; p = q) {
851                 q = p->next;
852                 kfree(p);
853         }
854         for (p = data->io_db.next; p != &data->io_db; p = q) {
855                 q = p->next;
856                 kfree(p);
857         }
858         up(&rsrc_sem);
859 }
860
861
862 struct pccard_resource_ops pccard_nonstatic_ops = {
863         .validate_mem = pcmcia_nonstatic_validate_mem,
864         .adjust_io_region = nonstatic_adjust_io_region,
865         .find_io = nonstatic_find_io_region,
866         .find_mem = nonstatic_find_mem_region,
867         .adjust_resource = nonstatic_adjust_resource_info,
868         .init = nonstatic_init,
869         .exit = nonstatic_release_resource_db,
870 };
871 EXPORT_SYMBOL(pccard_nonstatic_ops);
872
873
874 /* sysfs interface to the resource database */
875
876 static ssize_t show_io_db(struct class_device *class_dev, char *buf)
877 {
878         struct pcmcia_socket *s = class_get_devdata(class_dev);
879         struct socket_data *data;
880         struct resource_map *p;
881         ssize_t ret = 0;
882
883         down(&rsrc_sem);
884         data = s->resource_data;
885
886         for (p = data->io_db.next; p != &data->io_db; p = p->next) {
887                 if (ret > (PAGE_SIZE - 10))
888                         continue;
889                 ret += snprintf (&buf[ret], (PAGE_SIZE - ret - 1),
890                                  "0x%08lx - 0x%08lx\n",
891                                  ((unsigned long) p->base),
892                                  ((unsigned long) p->base + p->num - 1));
893         }
894
895         up(&rsrc_sem);
896         return (ret);
897 }
898
899 static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size_t count)
900 {
901         struct pcmcia_socket *s = class_get_devdata(class_dev);
902         unsigned long start_addr, end_addr;
903         unsigned int add = ADD_MANAGED_RESOURCE;
904         ssize_t ret = 0;
905
906         ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
907         if (ret != 2) {
908                 ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
909                 add = REMOVE_MANAGED_RESOURCE;
910                 if (ret != 2) {
911                         ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr);
912                         add = ADD_MANAGED_RESOURCE;
913                         if (ret != 2)
914                                 return -EINVAL;
915                 }
916         }
917         if (end_addr <= start_addr)
918                 return -EINVAL;
919
920         ret = adjust_io(s, add, start_addr, end_addr);
921         if (!ret)
922                 s->resource_setup_new = 1;
923
924         return ret ? ret : count;
925 }
926 static CLASS_DEVICE_ATTR(available_resources_io, 0600, show_io_db, store_io_db);
927
928 static ssize_t show_mem_db(struct class_device *class_dev, char *buf)
929 {
930         struct pcmcia_socket *s = class_get_devdata(class_dev);
931         struct socket_data *data;
932         struct resource_map *p;
933         ssize_t ret = 0;
934
935         down(&rsrc_sem);
936         data = s->resource_data;
937
938         for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
939                 if (ret > (PAGE_SIZE - 10))
940                         continue;
941                 ret += snprintf (&buf[ret], (PAGE_SIZE - ret - 1),
942                                  "0x%08lx - 0x%08lx\n",
943                                  ((unsigned long) p->base),
944                                  ((unsigned long) p->base + p->num - 1));
945         }
946
947         up(&rsrc_sem);
948         return (ret);
949 }
950
951 static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, size_t count)
952 {
953         struct pcmcia_socket *s = class_get_devdata(class_dev);
954         unsigned long start_addr, end_addr;
955         unsigned int add = ADD_MANAGED_RESOURCE;
956         ssize_t ret = 0;
957
958         ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
959         if (ret != 2) {
960                 ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
961                 add = REMOVE_MANAGED_RESOURCE;
962                 if (ret != 2) {
963                         ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr);
964                         add = ADD_MANAGED_RESOURCE;
965                         if (ret != 2)
966                                 return -EINVAL;
967                 }
968         }
969         if (end_addr <= start_addr)
970                 return -EINVAL;
971
972         ret = adjust_memory(s, add, start_addr, end_addr);
973         if (!ret)
974                 s->resource_setup_new = 1;
975
976         return ret ? ret : count;
977 }
978 static CLASS_DEVICE_ATTR(available_resources_mem, 0600, show_mem_db, store_mem_db);
979
980 static struct class_device_attribute *pccard_rsrc_attributes[] = {
981         &class_device_attr_available_resources_io,
982         &class_device_attr_available_resources_mem,
983         NULL,
984 };
985
986 static int __devinit pccard_sysfs_add_rsrc(struct class_device *class_dev)
987 {
988         struct pcmcia_socket *s = class_get_devdata(class_dev);
989         struct class_device_attribute **attr;
990         int ret = 0;
991         if (s->resource_ops != &pccard_nonstatic_ops)
992                 return 0;
993
994         for (attr = pccard_rsrc_attributes; *attr; attr++) {
995                 ret = class_device_create_file(class_dev, *attr);
996                 if (ret)
997                         break;
998         }
999
1000         return ret;
1001 }
1002
1003 static void __devexit pccard_sysfs_remove_rsrc(struct class_device *class_dev)
1004 {
1005         struct pcmcia_socket *s = class_get_devdata(class_dev);
1006         struct class_device_attribute **attr;
1007
1008         if (s->resource_ops != &pccard_nonstatic_ops)
1009                 return;
1010
1011         for (attr = pccard_rsrc_attributes; *attr; attr++)
1012                 class_device_remove_file(class_dev, *attr);
1013 }
1014
1015 static struct class_interface pccard_rsrc_interface = {
1016         .class = &pcmcia_socket_class,
1017         .add = &pccard_sysfs_add_rsrc,
1018         .remove = __devexit_p(&pccard_sysfs_remove_rsrc),
1019 };
1020
1021 static int __init nonstatic_sysfs_init(void)
1022 {
1023         return class_interface_register(&pccard_rsrc_interface);
1024 }
1025
1026 static void __exit nonstatic_sysfs_exit(void)
1027 {
1028         class_interface_unregister(&pccard_rsrc_interface);
1029 }
1030
1031 module_init(nonstatic_sysfs_init);
1032 module_exit(nonstatic_sysfs_exit);