Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * rsrc_nonstatic.c -- Resource management routines for !SS_CAP_STATIC_MAP sockets
4 : : *
5 : : * The initial developer of the original code is David A. Hinds
6 : : * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
7 : : * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
8 : : *
9 : : * (C) 1999 David A. Hinds
10 : : */
11 : :
12 : : #include <linux/module.h>
13 : : #include <linux/moduleparam.h>
14 : : #include <linux/init.h>
15 : : #include <linux/interrupt.h>
16 : : #include <linux/kernel.h>
17 : : #include <linux/errno.h>
18 : : #include <linux/types.h>
19 : : #include <linux/slab.h>
20 : : #include <linux/ioport.h>
21 : : #include <linux/timer.h>
22 : : #include <linux/pci.h>
23 : : #include <linux/device.h>
24 : : #include <linux/io.h>
25 : :
26 : : #include <asm/irq.h>
27 : :
28 : : #include <pcmcia/ss.h>
29 : : #include <pcmcia/cistpl.h>
30 : : #include "cs_internal.h"
31 : :
32 : : /* moved to rsrc_mgr.c
33 : : MODULE_AUTHOR("David A. Hinds, Dominik Brodowski");
34 : : MODULE_LICENSE("GPL");
35 : : */
36 : :
37 : : /* Parameters that can be set with 'insmod' */
38 : :
39 : : #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
40 : :
41 : : INT_MODULE_PARM(probe_mem, 1); /* memory probe? */
42 : : #ifdef CONFIG_PCMCIA_PROBE
43 : : INT_MODULE_PARM(probe_io, 1); /* IO port probe? */
44 : : INT_MODULE_PARM(mem_limit, 0x10000);
45 : : #endif
46 : :
47 : : /* for io_db and mem_db */
48 : : struct resource_map {
49 : : u_long base, num;
50 : : struct resource_map *next;
51 : : };
52 : :
53 : : struct socket_data {
54 : : struct resource_map mem_db;
55 : : struct resource_map mem_db_valid;
56 : : struct resource_map io_db;
57 : : };
58 : :
59 : : #define MEM_PROBE_LOW (1 << 0)
60 : : #define MEM_PROBE_HIGH (1 << 1)
61 : :
62 : : /* Action field */
63 : : #define REMOVE_MANAGED_RESOURCE 1
64 : : #define ADD_MANAGED_RESOURCE 2
65 : :
66 : : /*======================================================================
67 : :
68 : : Linux resource management extensions
69 : :
70 : : ======================================================================*/
71 : :
72 : : static struct resource *
73 : 0 : claim_region(struct pcmcia_socket *s, resource_size_t base,
74 : : resource_size_t size, int type, char *name)
75 : : {
76 : 0 : struct resource *res, *parent;
77 : :
78 [ # # ]: 0 : parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource;
79 : 0 : res = pcmcia_make_resource(base, size, type | IORESOURCE_BUSY, name);
80 : :
81 [ # # ]: 0 : if (res) {
82 : : #ifdef CONFIG_PCI
83 [ # # # # ]: 0 : if (s && s->cb_dev)
84 : 0 : parent = pci_find_parent_resource(s->cb_dev, res);
85 : : #endif
86 [ # # # # ]: 0 : if (!parent || request_resource(parent, res)) {
87 : 0 : kfree(res);
88 : 0 : res = NULL;
89 : : }
90 : : }
91 : 0 : return res;
92 : : }
93 : :
94 : 0 : static void free_region(struct resource *res)
95 : : {
96 : 0 : if (res) {
97 : 0 : release_resource(res);
98 : 0 : kfree(res);
99 : : }
100 : : }
101 : :
102 : : /*======================================================================
103 : :
104 : : These manage the internal databases of available resources.
105 : :
106 : : ======================================================================*/
107 : :
108 : 0 : static int add_interval(struct resource_map *map, u_long base, u_long num)
109 : : {
110 : 0 : struct resource_map *p, *q;
111 : :
112 : 0 : for (p = map; ; p = p->next) {
113 [ # # # # ]: 0 : if ((p != map) && (p->base+p->num >= base)) {
114 : 0 : p->num = max(num + base - p->base, p->num);
115 : 0 : return 0;
116 : : }
117 [ # # # # ]: 0 : if ((p->next == map) || (p->next->base > base+num-1))
118 : : break;
119 : : }
120 : 0 : q = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
121 [ # # ]: 0 : if (!q) {
122 : 0 : printk(KERN_WARNING "out of memory to update resources\n");
123 : 0 : return -ENOMEM;
124 : : }
125 : 0 : q->base = base; q->num = num;
126 : 0 : q->next = p->next; p->next = q;
127 : 0 : return 0;
128 : : }
129 : :
130 : : /*====================================================================*/
131 : :
132 : 0 : static int sub_interval(struct resource_map *map, u_long base, u_long num)
133 : : {
134 : 0 : struct resource_map *p, *q;
135 : :
136 : 0 : for (p = map; ; p = q) {
137 : 0 : q = p->next;
138 [ # # ]: 0 : if (q == map)
139 : : break;
140 [ # # # # ]: 0 : if ((q->base+q->num > base) && (base+num > q->base)) {
141 [ # # ]: 0 : if (q->base >= base) {
142 [ # # ]: 0 : if (q->base+q->num <= base+num) {
143 : : /* Delete whole block */
144 : 0 : p->next = q->next;
145 : 0 : kfree(q);
146 : : /* don't advance the pointer yet */
147 : 0 : q = p;
148 : : } else {
149 : : /* Cut off bit from the front */
150 : 0 : q->num = q->base + q->num - base - num;
151 : 0 : q->base = base + num;
152 : : }
153 [ # # ]: 0 : } else if (q->base+q->num <= base+num) {
154 : : /* Cut off bit from the end */
155 : 0 : q->num = base - q->base;
156 : : } else {
157 : : /* Split the block into two pieces */
158 : 0 : p = kmalloc(sizeof(struct resource_map),
159 : : GFP_KERNEL);
160 [ # # ]: 0 : if (!p) {
161 : 0 : printk(KERN_WARNING "out of memory to update resources\n");
162 : 0 : return -ENOMEM;
163 : : }
164 : 0 : p->base = base+num;
165 : 0 : p->num = q->base+q->num - p->base;
166 : 0 : q->num = base - q->base;
167 : 0 : p->next = q->next ; q->next = p;
168 : : }
169 : : }
170 : : }
171 : : return 0;
172 : : }
173 : :
174 : : /*======================================================================
175 : :
176 : : These routines examine a region of IO or memory addresses to
177 : : determine what ranges might be genuinely available.
178 : :
179 : : ======================================================================*/
180 : :
181 : : #ifdef CONFIG_PCMCIA_PROBE
182 : : static void do_io_probe(struct pcmcia_socket *s, unsigned int base,
183 : : unsigned int num)
184 : : {
185 : : struct resource *res;
186 : : struct socket_data *s_data = s->resource_data;
187 : : unsigned int i, j, bad;
188 : : int any;
189 : : u_char *b, hole, most;
190 : :
191 : : dev_info(&s->dev, "cs: IO port probe %#x-%#x:", base, base+num-1);
192 : :
193 : : /* First, what does a floating port look like? */
194 : : b = kzalloc(256, GFP_KERNEL);
195 : : if (!b) {
196 : : pr_cont("\n");
197 : : dev_err(&s->dev, "do_io_probe: unable to kmalloc 256 bytes\n");
198 : : return;
199 : : }
200 : : for (i = base, most = 0; i < base+num; i += 8) {
201 : : res = claim_region(s, i, 8, IORESOURCE_IO, "PCMCIA ioprobe");
202 : : if (!res)
203 : : continue;
204 : : hole = inb(i);
205 : : for (j = 1; j < 8; j++)
206 : : if (inb(i+j) != hole)
207 : : break;
208 : : free_region(res);
209 : : if ((j == 8) && (++b[hole] > b[most]))
210 : : most = hole;
211 : : if (b[most] == 127)
212 : : break;
213 : : }
214 : : kfree(b);
215 : :
216 : : bad = any = 0;
217 : : for (i = base; i < base+num; i += 8) {
218 : : res = claim_region(s, i, 8, IORESOURCE_IO, "PCMCIA ioprobe");
219 : : if (!res) {
220 : : if (!any)
221 : : pr_cont(" excluding");
222 : : if (!bad)
223 : : bad = any = i;
224 : : continue;
225 : : }
226 : : for (j = 0; j < 8; j++)
227 : : if (inb(i+j) != most)
228 : : break;
229 : : free_region(res);
230 : : if (j < 8) {
231 : : if (!any)
232 : : pr_cont(" excluding");
233 : : if (!bad)
234 : : bad = any = i;
235 : : } else {
236 : : if (bad) {
237 : : sub_interval(&s_data->io_db, bad, i-bad);
238 : : pr_cont(" %#x-%#x", bad, i-1);
239 : : bad = 0;
240 : : }
241 : : }
242 : : }
243 : : if (bad) {
244 : : if ((num > 16) && (bad == base) && (i == base+num)) {
245 : : sub_interval(&s_data->io_db, bad, i-bad);
246 : : pr_cont(" nothing: probe failed.\n");
247 : : return;
248 : : } else {
249 : : sub_interval(&s_data->io_db, bad, i-bad);
250 : : pr_cont(" %#x-%#x", bad, i-1);
251 : : }
252 : : }
253 : :
254 : : pr_cont("%s\n", !any ? " clean" : "");
255 : : }
256 : : #endif
257 : :
258 : : /*======================================================================*/
259 : :
260 : : /**
261 : : * readable() - iomem validation function for cards with a valid CIS
262 : : */
263 : 0 : static int readable(struct pcmcia_socket *s, struct resource *res,
264 : : unsigned int *count)
265 : : {
266 : 0 : int ret = -EINVAL;
267 : :
268 [ # # ]: 0 : if (s->fake_cis) {
269 : : dev_dbg(&s->dev, "fake CIS is being used: can't validate mem\n");
270 : : return 0;
271 : : }
272 : :
273 : 0 : s->cis_mem.res = res;
274 : 0 : s->cis_virt = ioremap(res->start, s->map_size);
275 [ # # ]: 0 : if (s->cis_virt) {
276 : 0 : mutex_unlock(&s->ops_mutex);
277 : : /* as we're only called from pcmcia.c, we're safe */
278 [ # # ]: 0 : if (s->callback->validate)
279 : 0 : ret = s->callback->validate(s, count);
280 : : /* invalidate mapping */
281 : 0 : mutex_lock(&s->ops_mutex);
282 : 0 : iounmap(s->cis_virt);
283 : 0 : s->cis_virt = NULL;
284 : : }
285 : 0 : s->cis_mem.res = NULL;
286 [ # # # # ]: 0 : if ((ret) || (*count == 0))
287 : 0 : return -EINVAL;
288 : : return 0;
289 : : }
290 : :
291 : : /**
292 : : * checksum() - iomem validation function for simple memory cards
293 : : */
294 : 0 : static int checksum(struct pcmcia_socket *s, struct resource *res,
295 : : unsigned int *value)
296 : : {
297 : 0 : pccard_mem_map map;
298 : 0 : int i, a = 0, b = -1, d;
299 : 0 : void __iomem *virt;
300 : :
301 : 0 : virt = ioremap(res->start, s->map_size);
302 [ # # ]: 0 : if (virt) {
303 : 0 : map.map = 0;
304 : 0 : map.flags = MAP_ACTIVE;
305 : 0 : map.speed = 0;
306 : 0 : map.res = res;
307 : 0 : map.card_start = 0;
308 : 0 : s->ops->set_mem_map(s, &map);
309 : :
310 : : /* Don't bother checking every word... */
311 [ # # ]: 0 : for (i = 0; i < s->map_size; i += 44) {
312 : 0 : d = readl(virt+i);
313 : 0 : a += d;
314 : 0 : b &= d;
315 : : }
316 : :
317 : 0 : map.flags = 0;
318 : 0 : s->ops->set_mem_map(s, &map);
319 : :
320 : 0 : iounmap(virt);
321 : : }
322 : :
323 [ # # ]: 0 : if (b == -1)
324 : 0 : return -EINVAL;
325 : :
326 : 0 : *value = a;
327 : :
328 : 0 : return 0;
329 : : }
330 : :
331 : : /**
332 : : * do_validate_mem() - low level validate a memory region for PCMCIA use
333 : : * @s: PCMCIA socket to validate
334 : : * @base: start address of resource to check
335 : : * @size: size of resource to check
336 : : * @validate: validation function to use
337 : : *
338 : : * do_validate_mem() splits up the memory region which is to be checked
339 : : * into two parts. Both are passed to the @validate() function. If
340 : : * @validate() returns non-zero, or the value parameter to @validate()
341 : : * is zero, or the value parameter is different between both calls,
342 : : * the check fails, and -EINVAL is returned. Else, 0 is returned.
343 : : */
344 : 0 : static int do_validate_mem(struct pcmcia_socket *s,
345 : : unsigned long base, unsigned long size,
346 : : int validate (struct pcmcia_socket *s,
347 : : struct resource *res,
348 : : unsigned int *value))
349 : : {
350 : 0 : struct socket_data *s_data = s->resource_data;
351 : 0 : struct resource *res1, *res2;
352 : 0 : unsigned int info1 = 1, info2 = 1;
353 : 0 : int ret = -EINVAL;
354 : :
355 : 0 : res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "PCMCIA memprobe");
356 : 0 : res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM,
357 : : "PCMCIA memprobe");
358 : :
359 [ # # ]: 0 : if (res1 && res2) {
360 : 0 : ret = 0;
361 [ # # ]: 0 : if (validate) {
362 : 0 : ret = validate(s, res1, &info1);
363 : 0 : ret += validate(s, res2, &info2);
364 : : }
365 : : }
366 : :
367 : 0 : dev_dbg(&s->dev, "cs: memory probe 0x%06lx-0x%06lx: %pr %pr %u %u %u",
368 : : base, base+size-1, res1, res2, ret, info1, info2);
369 : :
370 [ # # ]: 0 : free_region(res2);
371 [ # # ]: 0 : free_region(res1);
372 : :
373 [ # # # # : 0 : if ((ret) || (info1 != info2) || (info1 == 0))
# # ]
374 : : return -EINVAL;
375 : :
376 [ # # # # ]: 0 : if (validate && !s->fake_cis) {
377 : : /* move it to the validated data set */
378 : 0 : add_interval(&s_data->mem_db_valid, base, size);
379 : 0 : sub_interval(&s_data->mem_db, base, size);
380 : : }
381 : :
382 : : return 0;
383 : : }
384 : :
385 : :
386 : : /**
387 : : * do_mem_probe() - validate a memory region for PCMCIA use
388 : : * @s: PCMCIA socket to validate
389 : : * @base: start address of resource to check
390 : : * @num: size of resource to check
391 : : * @validate: validation function to use
392 : : * @fallback: validation function to use if validate fails
393 : : *
394 : : * do_mem_probe() checks a memory region for use by the PCMCIA subsystem.
395 : : * To do so, the area is split up into sensible parts, and then passed
396 : : * into the @validate() function. Only if @validate() and @fallback() fail,
397 : : * the area is marked as unavaibale for use by the PCMCIA subsystem. The
398 : : * function returns the size of the usable memory area.
399 : : */
400 : 0 : static int do_mem_probe(struct pcmcia_socket *s, u_long base, u_long num,
401 : : int validate (struct pcmcia_socket *s,
402 : : struct resource *res,
403 : : unsigned int *value),
404 : : int fallback (struct pcmcia_socket *s,
405 : : struct resource *res,
406 : : unsigned int *value))
407 : : {
408 : 0 : struct socket_data *s_data = s->resource_data;
409 : 0 : u_long i, j, bad, fail, step;
410 : :
411 : 0 : dev_info(&s->dev, "cs: memory probe 0x%06lx-0x%06lx:",
412 : : base, base+num-1);
413 : 0 : bad = fail = 0;
414 [ # # ]: 0 : step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
415 : : /* don't allow too large steps */
416 : 0 : if (step > 0x800000)
417 : : step = 0x800000;
418 : : /* cis_readable wants to map 2x map_size */
419 : 0 : if (step < 2 * s->map_size)
420 : : step = 2 * s->map_size;
421 [ # # ]: 0 : for (i = j = base; i < base+num; i = j + step) {
422 [ # # ]: 0 : if (!fail) {
423 [ # # ]: 0 : for (j = i; j < base+num; j += step) {
424 [ # # ]: 0 : if (!do_validate_mem(s, j, step, validate))
425 : : break;
426 : : }
427 [ # # # # ]: 0 : fail = ((i == base) && (j == base+num));
428 : : }
429 [ # # ]: 0 : if ((fail) && (fallback)) {
430 [ # # ]: 0 : for (j = i; j < base+num; j += step)
431 [ # # ]: 0 : if (!do_validate_mem(s, j, step, fallback))
432 : : break;
433 : : }
434 [ # # ]: 0 : if (i != j) {
435 [ # # ]: 0 : if (!bad)
436 : 0 : pr_cont(" excluding");
437 : 0 : pr_cont(" %#05lx-%#05lx", i, j-1);
438 : 0 : sub_interval(&s_data->mem_db, i, j-i);
439 : 0 : bad += j-i;
440 : : }
441 : : }
442 [ # # ]: 0 : pr_cont("%s\n", !bad ? " clean" : "");
443 : 0 : return num - bad;
444 : : }
445 : :
446 : :
447 : : #ifdef CONFIG_PCMCIA_PROBE
448 : :
449 : : /**
450 : : * inv_probe() - top-to-bottom search for one usuable high memory area
451 : : * @s: PCMCIA socket to validate
452 : : * @m: resource_map to check
453 : : */
454 : : static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
455 : : {
456 : : struct socket_data *s_data = s->resource_data;
457 : : u_long ok;
458 : : if (m == &s_data->mem_db)
459 : : return 0;
460 : : ok = inv_probe(m->next, s);
461 : : if (ok) {
462 : : if (m->base >= 0x100000)
463 : : sub_interval(&s_data->mem_db, m->base, m->num);
464 : : return ok;
465 : : }
466 : : if (m->base < 0x100000)
467 : : return 0;
468 : : return do_mem_probe(s, m->base, m->num, readable, checksum);
469 : : }
470 : :
471 : : /**
472 : : * validate_mem() - memory probe function
473 : : * @s: PCMCIA socket to validate
474 : : * @probe_mask: MEM_PROBE_LOW | MEM_PROBE_HIGH
475 : : *
476 : : * The memory probe. If the memory list includes a 64K-aligned block
477 : : * below 1MB, we probe in 64K chunks, and as soon as we accumulate at
478 : : * least mem_limit free space, we quit. Returns 0 on usuable ports.
479 : : */
480 : : static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
481 : : {
482 : : struct resource_map *m, mm;
483 : : static unsigned char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
484 : : unsigned long b, i, ok = 0;
485 : : struct socket_data *s_data = s->resource_data;
486 : :
487 : : /* We do up to four passes through the list */
488 : : if (probe_mask & MEM_PROBE_HIGH) {
489 : : if (inv_probe(s_data->mem_db.next, s) > 0)
490 : : return 0;
491 : : if (s_data->mem_db_valid.next != &s_data->mem_db_valid)
492 : : return 0;
493 : : dev_notice(&s->dev,
494 : : "cs: warning: no high memory space available!\n");
495 : : return -ENODEV;
496 : : }
497 : :
498 : : for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
499 : : mm = *m;
500 : : /* Only probe < 1 MB */
501 : : if (mm.base >= 0x100000)
502 : : continue;
503 : : if ((mm.base | mm.num) & 0xffff) {
504 : : ok += do_mem_probe(s, mm.base, mm.num, readable,
505 : : checksum);
506 : : continue;
507 : : }
508 : : /* Special probe for 64K-aligned block */
509 : : for (i = 0; i < 4; i++) {
510 : : b = order[i] << 12;
511 : : if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
512 : : if (ok >= mem_limit)
513 : : sub_interval(&s_data->mem_db, b, 0x10000);
514 : : else
515 : : ok += do_mem_probe(s, b, 0x10000,
516 : : readable, checksum);
517 : : }
518 : : }
519 : : }
520 : :
521 : : if (ok > 0)
522 : : return 0;
523 : :
524 : : return -ENODEV;
525 : : }
526 : :
527 : : #else /* CONFIG_PCMCIA_PROBE */
528 : :
529 : : /**
530 : : * validate_mem() - memory probe function
531 : : * @s: PCMCIA socket to validate
532 : : * @probe_mask: ignored
533 : : *
534 : : * Returns 0 on usuable ports.
535 : : */
536 : : static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
537 : : {
538 : : struct resource_map *m, mm;
539 : : struct socket_data *s_data = s->resource_data;
540 : : unsigned long ok = 0;
541 : :
542 : : for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
543 : : mm = *m;
544 : : ok += do_mem_probe(s, mm.base, mm.num, readable, checksum);
545 : : }
546 : : if (ok > 0)
547 : : return 0;
548 : : return -ENODEV;
549 : : }
550 : :
551 : : #endif /* CONFIG_PCMCIA_PROBE */
552 : :
553 : :
554 : : /**
555 : : * pcmcia_nonstatic_validate_mem() - try to validate iomem for PCMCIA use
556 : : * @s: PCMCIA socket to validate
557 : : *
558 : : * This is tricky... when we set up CIS memory, we try to validate
559 : : * the memory window space allocations.
560 : : *
561 : : * Locking note: Must be called with skt_mutex held!
562 : : */
563 : 0 : static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
564 : : {
565 : 0 : struct socket_data *s_data = s->resource_data;
566 : 0 : unsigned int probe_mask = MEM_PROBE_LOW;
567 : 0 : int ret;
568 : :
569 [ # # # # ]: 0 : if (!probe_mem || !(s->state & SOCKET_PRESENT))
570 : : return 0;
571 : :
572 : 0 : if (s->features & SS_CAP_PAGE_REGS)
573 : : probe_mask = MEM_PROBE_HIGH;
574 : :
575 : 0 : ret = validate_mem(s, probe_mask);
576 : :
577 [ # # ]: 0 : if (s_data->mem_db_valid.next != &s_data->mem_db_valid)
578 : 0 : return 0;
579 : :
580 : : return ret;
581 : : }
582 : :
583 : : struct pcmcia_align_data {
584 : : unsigned long mask;
585 : : unsigned long offset;
586 : : struct resource_map *map;
587 : : };
588 : :
589 : 0 : static resource_size_t pcmcia_common_align(struct pcmcia_align_data *align_data,
590 : : resource_size_t start)
591 : : {
592 : 0 : resource_size_t ret;
593 : : /*
594 : : * Ensure that we have the correct start address
595 : : */
596 : 0 : ret = (start & ~align_data->mask) + align_data->offset;
597 : 0 : if (ret < start)
598 : 0 : ret += align_data->mask + 1;
599 : 0 : return ret;
600 : : }
601 : :
602 : : static resource_size_t
603 : 0 : pcmcia_align(void *align_data, const struct resource *res,
604 : : resource_size_t size, resource_size_t align)
605 : : {
606 : 0 : struct pcmcia_align_data *data = align_data;
607 : 0 : struct resource_map *m;
608 : 0 : resource_size_t start;
609 : :
610 [ # # ]: 0 : start = pcmcia_common_align(data, res->start);
611 : :
612 [ # # ]: 0 : for (m = data->map->next; m != data->map; m = m->next) {
613 : 0 : unsigned long map_start = m->base;
614 : 0 : unsigned long map_end = m->base + m->num - 1;
615 : :
616 : : /*
617 : : * If the lower resources are not available, try aligning
618 : : * to this entry of the resource database to see if it'll
619 : : * fit here.
620 : : */
621 [ # # ]: 0 : if (start < map_start)
622 [ # # ]: 0 : start = pcmcia_common_align(data, map_start);
623 : :
624 : : /*
625 : : * If we're above the area which was passed in, there's
626 : : * no point proceeding.
627 : : */
628 [ # # ]: 0 : if (start >= res->end)
629 : : break;
630 : :
631 [ # # ]: 0 : if ((start + size - 1) <= map_end)
632 : : break;
633 : : }
634 : :
635 : : /*
636 : : * If we failed to find something suitable, ensure we fail.
637 : : */
638 [ # # ]: 0 : if (m == data->map)
639 : 0 : start = res->end;
640 : :
641 : 0 : return start;
642 : : }
643 : :
644 : : /*
645 : : * Adjust an existing IO region allocation, but making sure that we don't
646 : : * encroach outside the resources which the user supplied.
647 : : */
648 : 0 : static int __nonstatic_adjust_io_region(struct pcmcia_socket *s,
649 : : unsigned long r_start,
650 : : unsigned long r_end)
651 : : {
652 : 0 : struct resource_map *m;
653 : 0 : struct socket_data *s_data = s->resource_data;
654 : 0 : int ret = -ENOMEM;
655 : :
656 [ # # # # ]: 0 : for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) {
657 : 0 : unsigned long start = m->base;
658 : 0 : unsigned long end = m->base + m->num - 1;
659 : :
660 [ # # # # ]: 0 : if (start > r_start || r_end > end)
661 : 0 : continue;
662 : :
663 : : ret = 0;
664 : : }
665 : :
666 : 0 : return ret;
667 : : }
668 : :
669 : : /*======================================================================
670 : :
671 : : These find ranges of I/O ports or memory addresses that are not
672 : : currently allocated by other devices.
673 : :
674 : : The 'align' field should reflect the number of bits of address
675 : : that need to be preserved from the initial value of *base. It
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
678 : : also be strictly less than 'align'.
679 : :
680 : : ======================================================================*/
681 : :
682 : 0 : static struct resource *__nonstatic_find_io_region(struct pcmcia_socket *s,
683 : : unsigned long base, int num,
684 : : unsigned long align)
685 : : {
686 [ # # ]: 0 : struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO,
687 : : dev_name(&s->dev));
688 : 0 : struct socket_data *s_data = s->resource_data;
689 : 0 : struct pcmcia_align_data data;
690 : 0 : unsigned long min = base;
691 : 0 : int ret;
692 : :
693 : 0 : data.mask = align - 1;
694 : 0 : data.offset = base & data.mask;
695 : 0 : data.map = &s_data->io_db;
696 : :
697 : : #ifdef CONFIG_PCI
698 [ # # ]: 0 : if (s->cb_dev) {
699 : 0 : ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
700 : : min, 0, pcmcia_align, &data);
701 : : } else
702 : : #endif
703 : 0 : ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
704 : : 1, pcmcia_align, &data);
705 : :
706 [ # # ]: 0 : if (ret != 0) {
707 : 0 : kfree(res);
708 : 0 : res = NULL;
709 : : }
710 : 0 : return res;
711 : : }
712 : :
713 : 0 : static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
714 : : unsigned int *base, unsigned int num,
715 : : unsigned int align, struct resource **parent)
716 : : {
717 : 0 : int i, ret = 0;
718 : :
719 : : /* Check for an already-allocated window that must conflict with
720 : : * what was asked for. It is a hack because it does not catch all
721 : : * potential conflicts, just the most obvious ones.
722 : : */
723 [ # # ]: 0 : for (i = 0; i < MAX_IO_WIN; i++) {
724 [ # # ]: 0 : if (!s->io[i].res)
725 : 0 : continue;
726 : :
727 [ # # ]: 0 : if (!*base)
728 : 0 : continue;
729 : :
730 [ # # ]: 0 : if ((s->io[i].res->start & (align-1)) == *base)
731 : : return -EBUSY;
732 : : }
733 : :
734 [ # # ]: 0 : for (i = 0; i < MAX_IO_WIN; i++) {
735 : 0 : struct resource *res = s->io[i].res;
736 : 0 : unsigned int try;
737 : :
738 [ # # ]: 0 : if (res && (res->flags & IORESOURCE_BITS) !=
739 [ # # ]: 0 : (attr & IORESOURCE_BITS))
740 : 0 : continue;
741 : :
742 [ # # ]: 0 : if (!res) {
743 [ # # ]: 0 : if (align == 0)
744 : 0 : align = 0x10000;
745 : :
746 : 0 : res = s->io[i].res = __nonstatic_find_io_region(s,
747 : 0 : *base, num,
748 : : align);
749 [ # # ]: 0 : if (!res)
750 : : return -EINVAL;
751 : :
752 : 0 : *base = res->start;
753 : 0 : s->io[i].res->flags =
754 : 0 : ((res->flags & ~IORESOURCE_BITS) |
755 : 0 : (attr & IORESOURCE_BITS));
756 : 0 : s->io[i].InUse = num;
757 : 0 : *parent = res;
758 : 0 : return 0;
759 : : }
760 : :
761 : : /* Try to extend top of window */
762 : 0 : try = res->end + 1;
763 [ # # # # ]: 0 : if ((*base == 0) || (*base == try)) {
764 : 0 : ret = __nonstatic_adjust_io_region(s, res->start,
765 : 0 : res->end + num);
766 [ # # ]: 0 : if (!ret) {
767 : 0 : ret = adjust_resource(s->io[i].res, res->start,
768 : : resource_size(res) + num);
769 [ # # ]: 0 : if (ret)
770 : 0 : continue;
771 : 0 : *base = try;
772 : 0 : s->io[i].InUse += num;
773 : 0 : *parent = res;
774 : 0 : return 0;
775 : : }
776 : : }
777 : :
778 : : /* Try to extend bottom of window */
779 : 0 : try = res->start - num;
780 [ # # # # ]: 0 : if ((*base == 0) || (*base == try)) {
781 : 0 : ret = __nonstatic_adjust_io_region(s,
782 : 0 : res->start - num,
783 : : res->end);
784 [ # # ]: 0 : if (!ret) {
785 : 0 : ret = adjust_resource(s->io[i].res,
786 : : res->start - num,
787 : : resource_size(res) + num);
788 [ # # ]: 0 : if (ret)
789 : 0 : continue;
790 : 0 : *base = try;
791 : 0 : s->io[i].InUse += num;
792 : 0 : *parent = res;
793 : 0 : return 0;
794 : : }
795 : : }
796 : : }
797 : :
798 : : return -EINVAL;
799 : : }
800 : :
801 : :
802 : 0 : static struct resource *nonstatic_find_mem_region(u_long base, u_long num,
803 : : u_long align, int low, struct pcmcia_socket *s)
804 : : {
805 [ # # ]: 0 : struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_MEM,
806 : : dev_name(&s->dev));
807 : 0 : struct socket_data *s_data = s->resource_data;
808 : 0 : struct pcmcia_align_data data;
809 : 0 : unsigned long min, max;
810 : 0 : int ret, i, j;
811 : :
812 [ # # ]: 0 : low = low || !(s->features & SS_CAP_PAGE_REGS);
813 : :
814 : 0 : data.mask = align - 1;
815 : 0 : data.offset = base & data.mask;
816 : :
817 [ # # ]: 0 : for (i = 0; i < 2; i++) {
818 : 0 : data.map = &s_data->mem_db_valid;
819 [ # # ]: 0 : if (low) {
820 : 0 : max = 0x100000UL;
821 [ # # ]: 0 : min = base < max ? base : 0;
822 : : } else {
823 : 0 : max = ~0UL;
824 : 0 : min = 0x100000UL + base;
825 : : }
826 : :
827 [ # # ]: 0 : for (j = 0; j < 2; j++) {
828 : : #ifdef CONFIG_PCI
829 [ # # ]: 0 : if (s->cb_dev) {
830 : 0 : ret = pci_bus_alloc_resource(s->cb_dev->bus,
831 : : res, num, 1, min, 0,
832 : : pcmcia_align, &data);
833 : : } else
834 : : #endif
835 : : {
836 : 0 : ret = allocate_resource(&iomem_resource,
837 : : res, num, min, max, 1,
838 : : pcmcia_align, &data);
839 : : }
840 [ # # ]: 0 : if (ret == 0)
841 : : break;
842 : 0 : data.map = &s_data->mem_db;
843 : : }
844 [ # # ]: 0 : if (ret == 0 || low)
845 : : break;
846 : 0 : low = 1;
847 : : }
848 : :
849 [ # # ]: 0 : if (ret != 0) {
850 : 0 : kfree(res);
851 : 0 : res = NULL;
852 : : }
853 : 0 : return res;
854 : : }
855 : :
856 : :
857 : 0 : static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
858 : : {
859 : 0 : struct socket_data *data = s->resource_data;
860 : 0 : unsigned long size = end - start + 1;
861 : 0 : int ret = 0;
862 : :
863 [ # # ]: 0 : if (end < start)
864 : : return -EINVAL;
865 : :
866 [ # # # ]: 0 : switch (action) {
867 : 0 : case ADD_MANAGED_RESOURCE:
868 : 0 : ret = add_interval(&data->mem_db, start, size);
869 [ # # ]: 0 : if (!ret)
870 : 0 : do_mem_probe(s, start, size, NULL, NULL);
871 : : break;
872 : 0 : case REMOVE_MANAGED_RESOURCE:
873 : 0 : ret = sub_interval(&data->mem_db, start, size);
874 : 0 : break;
875 : : default:
876 : : ret = -EINVAL;
877 : : }
878 : :
879 : : return ret;
880 : : }
881 : :
882 : :
883 : : static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
884 : : {
885 : : struct socket_data *data = s->resource_data;
886 : : unsigned long size;
887 : : int ret = 0;
888 : :
889 : : #if defined(CONFIG_X86)
890 : : /* on x86, avoid anything < 0x100 for it is often used for
891 : : * legacy platform devices */
892 : : if (start < 0x100)
893 : : start = 0x100;
894 : : #endif
895 : :
896 : : size = end - start + 1;
897 : :
898 : : if (end < start)
899 : : return -EINVAL;
900 : :
901 : : if (end > IO_SPACE_LIMIT)
902 : : return -EINVAL;
903 : :
904 : : switch (action) {
905 : : case ADD_MANAGED_RESOURCE:
906 : : if (add_interval(&data->io_db, start, size) != 0) {
907 : : ret = -EBUSY;
908 : : break;
909 : : }
910 : : #ifdef CONFIG_PCMCIA_PROBE
911 : : if (probe_io)
912 : : do_io_probe(s, start, size);
913 : : #endif
914 : : break;
915 : : case REMOVE_MANAGED_RESOURCE:
916 : : sub_interval(&data->io_db, start, size);
917 : : break;
918 : : default:
919 : : ret = -EINVAL;
920 : : break;
921 : : }
922 : :
923 : : return ret;
924 : : }
925 : :
926 : :
927 : : #ifdef CONFIG_PCI
928 : 0 : static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
929 : : {
930 : 0 : struct resource *res;
931 : 0 : int i, done = 0;
932 : :
933 [ # # # # ]: 0 : if (!s->cb_dev || !s->cb_dev->bus)
934 : : return -ENODEV;
935 : :
936 : : #if defined(CONFIG_X86)
937 : : /* If this is the root bus, the risk of hitting some strange
938 : : * system devices is too high: If a driver isn't loaded, the
939 : : * resources are not claimed; even if a driver is loaded, it
940 : : * may not request all resources or even the wrong one. We
941 : : * can neither trust the rest of the kernel nor ACPI/PNP and
942 : : * CRS parsing to get it right. Therefore, use several
943 : : * safeguards:
944 : : *
945 : : * - Do not auto-add resources if the CardBus bridge is on
946 : : * the PCI root bus
947 : : *
948 : : * - Avoid any I/O ports < 0x100.
949 : : *
950 : : * - On PCI-PCI bridges, only use resources which are set up
951 : : * exclusively for the secondary PCI bus: the risk of hitting
952 : : * system devices is quite low, as they usually aren't
953 : : * connected to the secondary PCI bus.
954 : : */
955 [ # # ]: 0 : if (s->cb_dev->bus->number == 0)
956 : : return -EINVAL;
957 : :
958 [ # # ]: 0 : for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) {
959 : 0 : res = s->cb_dev->bus->resource[i];
960 : : #else
961 : : pci_bus_for_each_resource(s->cb_dev->bus, res, i) {
962 : : #endif
963 [ # # ]: 0 : if (!res)
964 : 0 : continue;
965 : :
966 [ # # ]: 0 : if (res->flags & IORESOURCE_IO) {
967 : : /* safeguard against the root resource, where the
968 : : * risk of hitting any other device would be too
969 : : * high */
970 [ # # ]: 0 : if (res == &ioport_resource)
971 : 0 : continue;
972 : :
973 : 0 : dev_info(&s->cb_dev->dev,
974 : : "pcmcia: parent PCI bridge window: %pR\n",
975 : : res);
976 [ # # ]: 0 : if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end))
977 : 0 : done |= IORESOURCE_IO;
978 : :
979 : : }
980 : :
981 [ # # ]: 0 : if (res->flags & IORESOURCE_MEM) {
982 : : /* safeguard against the root resource, where the
983 : : * risk of hitting any other device would be too
984 : : * high */
985 [ # # ]: 0 : if (res == &iomem_resource)
986 : 0 : continue;
987 : :
988 : 0 : dev_info(&s->cb_dev->dev,
989 : : "pcmcia: parent PCI bridge window: %pR\n",
990 : : res);
991 [ # # ]: 0 : if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end))
992 : 0 : done |= IORESOURCE_MEM;
993 : : }
994 : : }
995 : :
996 : : /* if we got at least one of IO, and one of MEM, we can be glad and
997 : : * activate the PCMCIA subsystem */
998 [ # # ]: 0 : if (done == (IORESOURCE_MEM | IORESOURCE_IO))
999 : 0 : s->resource_setup_done = 1;
1000 : :
1001 : : return 0;
1002 : : }
1003 : :
1004 : : #else
1005 : :
1006 : : static inline int nonstatic_autoadd_resources(struct pcmcia_socket *s)
1007 : : {
1008 : : return -ENODEV;
1009 : : }
1010 : :
1011 : : #endif
1012 : :
1013 : :
1014 : 0 : static int nonstatic_init(struct pcmcia_socket *s)
1015 : : {
1016 : 0 : struct socket_data *data;
1017 : :
1018 : 0 : data = kzalloc(sizeof(struct socket_data), GFP_KERNEL);
1019 [ # # ]: 0 : if (!data)
1020 : : return -ENOMEM;
1021 : :
1022 : 0 : data->mem_db.next = &data->mem_db;
1023 : 0 : data->mem_db_valid.next = &data->mem_db_valid;
1024 : 0 : data->io_db.next = &data->io_db;
1025 : :
1026 : 0 : s->resource_data = (void *) data;
1027 : :
1028 : 0 : nonstatic_autoadd_resources(s);
1029 : :
1030 : 0 : return 0;
1031 : : }
1032 : :
1033 : 0 : static void nonstatic_release_resource_db(struct pcmcia_socket *s)
1034 : : {
1035 : 0 : struct socket_data *data = s->resource_data;
1036 : 0 : struct resource_map *p, *q;
1037 : :
1038 [ # # ]: 0 : for (p = data->mem_db_valid.next; p != &data->mem_db_valid; p = q) {
1039 : 0 : q = p->next;
1040 : 0 : kfree(p);
1041 : : }
1042 [ # # ]: 0 : for (p = data->mem_db.next; p != &data->mem_db; p = q) {
1043 : 0 : q = p->next;
1044 : 0 : kfree(p);
1045 : : }
1046 [ # # ]: 0 : for (p = data->io_db.next; p != &data->io_db; p = q) {
1047 : 0 : q = p->next;
1048 : 0 : kfree(p);
1049 : : }
1050 : 0 : }
1051 : :
1052 : :
1053 : : struct pccard_resource_ops pccard_nonstatic_ops = {
1054 : : .validate_mem = pcmcia_nonstatic_validate_mem,
1055 : : .find_io = nonstatic_find_io,
1056 : : .find_mem = nonstatic_find_mem_region,
1057 : : .init = nonstatic_init,
1058 : : .exit = nonstatic_release_resource_db,
1059 : : };
1060 : : EXPORT_SYMBOL(pccard_nonstatic_ops);
1061 : :
1062 : :
1063 : : /* sysfs interface to the resource database */
1064 : :
1065 : 0 : static ssize_t show_io_db(struct device *dev,
1066 : : struct device_attribute *attr, char *buf)
1067 : : {
1068 : 0 : struct pcmcia_socket *s = dev_get_drvdata(dev);
1069 : 0 : struct socket_data *data;
1070 : 0 : struct resource_map *p;
1071 : 0 : ssize_t ret = 0;
1072 : :
1073 : 0 : mutex_lock(&s->ops_mutex);
1074 : 0 : data = s->resource_data;
1075 : :
1076 [ # # ]: 0 : for (p = data->io_db.next; p != &data->io_db; p = p->next) {
1077 [ # # ]: 0 : if (ret > (PAGE_SIZE - 10))
1078 : 0 : continue;
1079 : 0 : ret += snprintf(&buf[ret], (PAGE_SIZE - ret - 1),
1080 : : "0x%08lx - 0x%08lx\n",
1081 : : ((unsigned long) p->base),
1082 : 0 : ((unsigned long) p->base + p->num - 1));
1083 : : }
1084 : :
1085 : 0 : mutex_unlock(&s->ops_mutex);
1086 : 0 : return ret;
1087 : : }
1088 : :
1089 : 0 : static ssize_t store_io_db(struct device *dev,
1090 : : struct device_attribute *attr,
1091 : : const char *buf, size_t count)
1092 : : {
1093 [ # # ]: 0 : struct pcmcia_socket *s = dev_get_drvdata(dev);
1094 : 0 : unsigned long start_addr, end_addr;
1095 : 0 : unsigned int add = ADD_MANAGED_RESOURCE;
1096 : 0 : ssize_t ret = 0;
1097 : :
1098 : 0 : ret = sscanf(buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
1099 [ # # ]: 0 : if (ret != 2) {
1100 : 0 : ret = sscanf(buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
1101 : 0 : add = REMOVE_MANAGED_RESOURCE;
1102 [ # # ]: 0 : if (ret != 2) {
1103 : 0 : ret = sscanf(buf, "0x%lx - 0x%lx", &start_addr,
1104 : : &end_addr);
1105 : 0 : add = ADD_MANAGED_RESOURCE;
1106 [ # # ]: 0 : if (ret != 2)
1107 : : return -EINVAL;
1108 : : }
1109 : : }
1110 [ # # ]: 0 : if (end_addr < start_addr)
1111 : : return -EINVAL;
1112 : :
1113 : 0 : mutex_lock(&s->ops_mutex);
1114 : 0 : ret = adjust_io(s, add, start_addr, end_addr);
1115 : 0 : mutex_unlock(&s->ops_mutex);
1116 : :
1117 [ # # ]: 0 : return ret ? ret : count;
1118 : : }
1119 : : static DEVICE_ATTR(available_resources_io, 0600, show_io_db, store_io_db);
1120 : :
1121 : 0 : static ssize_t show_mem_db(struct device *dev,
1122 : : struct device_attribute *attr, char *buf)
1123 : : {
1124 : 0 : struct pcmcia_socket *s = dev_get_drvdata(dev);
1125 : 0 : struct socket_data *data;
1126 : 0 : struct resource_map *p;
1127 : 0 : ssize_t ret = 0;
1128 : :
1129 : 0 : mutex_lock(&s->ops_mutex);
1130 : 0 : data = s->resource_data;
1131 : :
1132 [ # # ]: 0 : for (p = data->mem_db_valid.next; p != &data->mem_db_valid;
1133 : 0 : p = p->next) {
1134 [ # # ]: 0 : if (ret > (PAGE_SIZE - 10))
1135 : 0 : continue;
1136 : 0 : ret += snprintf(&buf[ret], (PAGE_SIZE - ret - 1),
1137 : : "0x%08lx - 0x%08lx\n",
1138 : : ((unsigned long) p->base),
1139 : 0 : ((unsigned long) p->base + p->num - 1));
1140 : : }
1141 : :
1142 [ # # ]: 0 : for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
1143 [ # # ]: 0 : if (ret > (PAGE_SIZE - 10))
1144 : 0 : continue;
1145 : 0 : ret += snprintf(&buf[ret], (PAGE_SIZE - ret - 1),
1146 : : "0x%08lx - 0x%08lx\n",
1147 : : ((unsigned long) p->base),
1148 : 0 : ((unsigned long) p->base + p->num - 1));
1149 : : }
1150 : :
1151 : 0 : mutex_unlock(&s->ops_mutex);
1152 : 0 : return ret;
1153 : : }
1154 : :
1155 : 0 : static ssize_t store_mem_db(struct device *dev,
1156 : : struct device_attribute *attr,
1157 : : const char *buf, size_t count)
1158 : : {
1159 [ # # ]: 0 : struct pcmcia_socket *s = dev_get_drvdata(dev);
1160 : 0 : unsigned long start_addr, end_addr;
1161 : 0 : unsigned int add = ADD_MANAGED_RESOURCE;
1162 : 0 : ssize_t ret = 0;
1163 : :
1164 : 0 : ret = sscanf(buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
1165 [ # # ]: 0 : if (ret != 2) {
1166 : 0 : ret = sscanf(buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
1167 : 0 : add = REMOVE_MANAGED_RESOURCE;
1168 [ # # ]: 0 : if (ret != 2) {
1169 : 0 : ret = sscanf(buf, "0x%lx - 0x%lx", &start_addr,
1170 : : &end_addr);
1171 : 0 : add = ADD_MANAGED_RESOURCE;
1172 [ # # ]: 0 : if (ret != 2)
1173 : : return -EINVAL;
1174 : : }
1175 : : }
1176 [ # # ]: 0 : if (end_addr < start_addr)
1177 : : return -EINVAL;
1178 : :
1179 : 0 : mutex_lock(&s->ops_mutex);
1180 : 0 : ret = adjust_memory(s, add, start_addr, end_addr);
1181 : 0 : mutex_unlock(&s->ops_mutex);
1182 : :
1183 [ # # ]: 0 : return ret ? ret : count;
1184 : : }
1185 : : static DEVICE_ATTR(available_resources_mem, 0600, show_mem_db, store_mem_db);
1186 : :
1187 : : static struct attribute *pccard_rsrc_attributes[] = {
1188 : : &dev_attr_available_resources_io.attr,
1189 : : &dev_attr_available_resources_mem.attr,
1190 : : NULL,
1191 : : };
1192 : :
1193 : : static const struct attribute_group rsrc_attributes = {
1194 : : .attrs = pccard_rsrc_attributes,
1195 : : };
1196 : :
1197 : 0 : static int pccard_sysfs_add_rsrc(struct device *dev,
1198 : : struct class_interface *class_intf)
1199 : : {
1200 [ # # ]: 0 : struct pcmcia_socket *s = dev_get_drvdata(dev);
1201 : :
1202 [ # # ]: 0 : if (s->resource_ops != &pccard_nonstatic_ops)
1203 : : return 0;
1204 : 0 : return sysfs_create_group(&dev->kobj, &rsrc_attributes);
1205 : : }
1206 : :
1207 : 0 : static void pccard_sysfs_remove_rsrc(struct device *dev,
1208 : : struct class_interface *class_intf)
1209 : : {
1210 [ # # ]: 0 : struct pcmcia_socket *s = dev_get_drvdata(dev);
1211 : :
1212 [ # # ]: 0 : if (s->resource_ops != &pccard_nonstatic_ops)
1213 : : return;
1214 : 0 : sysfs_remove_group(&dev->kobj, &rsrc_attributes);
1215 : : }
1216 : :
1217 : : static struct class_interface pccard_rsrc_interface __refdata = {
1218 : : .class = &pcmcia_socket_class,
1219 : : .add_dev = &pccard_sysfs_add_rsrc,
1220 : : .remove_dev = &pccard_sysfs_remove_rsrc,
1221 : : };
1222 : :
1223 : 78 : static int __init nonstatic_sysfs_init(void)
1224 : : {
1225 : 78 : return class_interface_register(&pccard_rsrc_interface);
1226 : : }
1227 : :
1228 : 0 : static void __exit nonstatic_sysfs_exit(void)
1229 : : {
1230 : 0 : class_interface_unregister(&pccard_rsrc_interface);
1231 : 0 : }
1232 : :
1233 : : module_init(nonstatic_sysfs_init);
1234 : : module_exit(nonstatic_sysfs_exit);
|