diff options
Diffstat (limited to 'drivers/pcmcia/rsrc_nonstatic.c')
-rw-r--r-- | drivers/pcmcia/rsrc_nonstatic.c | 140 |
1 files changed, 75 insertions, 65 deletions
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 00960a379b9c..5301ac60358f 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c | |||
@@ -75,10 +75,9 @@ static DECLARE_MUTEX(rsrc_sem); | |||
75 | static struct resource * | 75 | static struct resource * |
76 | make_resource(unsigned long b, unsigned long n, int flags, char *name) | 76 | make_resource(unsigned long b, unsigned long n, int flags, char *name) |
77 | { | 77 | { |
78 | struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL); | 78 | struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); |
79 | 79 | ||
80 | if (res) { | 80 | if (res) { |
81 | memset(res, 0, sizeof(*res)); | ||
82 | res->name = name; | 81 | res->name = name; |
83 | res->start = b; | 82 | res->start = b; |
84 | res->end = b + n - 1; | 83 | res->end = b + n - 1; |
@@ -200,12 +199,11 @@ static void do_io_probe(struct pcmcia_socket *s, kio_addr_t base, kio_addr_t num | |||
200 | base, base+num-1); | 199 | base, base+num-1); |
201 | 200 | ||
202 | /* First, what does a floating port look like? */ | 201 | /* First, what does a floating port look like? */ |
203 | b = kmalloc(256, GFP_KERNEL); | 202 | b = kzalloc(256, GFP_KERNEL); |
204 | if (!b) { | 203 | if (!b) { |
205 | printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes"); | 204 | printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes"); |
206 | return; | 205 | return; |
207 | } | 206 | } |
208 | memset(b, 0, 256); | ||
209 | for (i = base, most = 0; i < base+num; i += 8) { | 207 | for (i = base, most = 0; i < base+num; i += 8) { |
210 | res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe"); | 208 | res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe"); |
211 | if (!res) | 209 | if (!res) |
@@ -407,69 +405,79 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s) | |||
407 | 405 | ||
408 | static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s) | 406 | static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s) |
409 | { | 407 | { |
410 | struct socket_data *s_data = s->resource_data; | 408 | struct socket_data *s_data = s->resource_data; |
411 | u_long ok; | 409 | u_long ok; |
412 | if (m == &s_data->mem_db) | 410 | if (m == &s_data->mem_db) |
413 | return 0; | 411 | return 0; |
414 | ok = inv_probe(m->next, s); | 412 | ok = inv_probe(m->next, s); |
415 | if (ok) { | 413 | if (ok) { |
416 | if (m->base >= 0x100000) | 414 | if (m->base >= 0x100000) |
417 | sub_interval(&s_data->mem_db, m->base, m->num); | 415 | sub_interval(&s_data->mem_db, m->base, m->num); |
418 | return ok; | 416 | return ok; |
419 | } | 417 | } |
420 | if (m->base < 0x100000) | 418 | if (m->base < 0x100000) |
421 | return 0; | 419 | return 0; |
422 | return do_mem_probe(m->base, m->num, s); | 420 | return do_mem_probe(m->base, m->num, s); |
423 | } | 421 | } |
424 | 422 | ||
425 | static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) | 423 | static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) |
426 | { | 424 | { |
427 | struct resource_map *m, mm; | 425 | struct resource_map *m, mm; |
428 | static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 }; | 426 | static unsigned char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 }; |
429 | u_long b, i, ok = 0; | 427 | unsigned long b, i, ok = 0; |
430 | struct socket_data *s_data = s->resource_data; | 428 | struct socket_data *s_data = s->resource_data; |
431 | 429 | ||
432 | /* We do up to four passes through the list */ | 430 | /* We do up to four passes through the list */ |
433 | if (probe_mask & MEM_PROBE_HIGH) { | 431 | if (probe_mask & MEM_PROBE_HIGH) { |
434 | if (inv_probe(s_data->mem_db.next, s) > 0) | 432 | if (inv_probe(s_data->mem_db.next, s) > 0) |
435 | return; | 433 | return 0; |
436 | printk(KERN_NOTICE "cs: warning: no high memory space " | 434 | printk(KERN_NOTICE "cs: warning: no high memory space " |
437 | "available!\n"); | 435 | "available!\n"); |
438 | } | 436 | return -ENODEV; |
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 | } | 437 | } |
449 | /* Special probe for 64K-aligned block */ | 438 | |
450 | for (i = 0; i < 4; i++) { | 439 | for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) { |
451 | b = order[i] << 12; | 440 | mm = *m; |
452 | if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) { | 441 | /* Only probe < 1 MB */ |
453 | if (ok >= mem_limit) | 442 | if (mm.base >= 0x100000) |
454 | sub_interval(&s_data->mem_db, b, 0x10000); | 443 | continue; |
455 | else | 444 | if ((mm.base | mm.num) & 0xffff) { |
456 | ok += do_mem_probe(b, 0x10000, s); | 445 | ok += do_mem_probe(mm.base, mm.num, s); |
457 | } | 446 | continue; |
447 | } | ||
448 | /* Special probe for 64K-aligned block */ | ||
449 | for (i = 0; i < 4; i++) { | ||
450 | b = order[i] << 12; | ||
451 | if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) { | ||
452 | if (ok >= mem_limit) | ||
453 | sub_interval(&s_data->mem_db, b, 0x10000); | ||
454 | else | ||
455 | ok += do_mem_probe(b, 0x10000, s); | ||
456 | } | ||
457 | } | ||
458 | } | 458 | } |
459 | } | 459 | |
460 | if (ok > 0) | ||
461 | return 0; | ||
462 | |||
463 | return -ENODEV; | ||
460 | } | 464 | } |
461 | 465 | ||
462 | #else /* CONFIG_PCMCIA_PROBE */ | 466 | #else /* CONFIG_PCMCIA_PROBE */ |
463 | 467 | ||
464 | static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) | 468 | static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) |
465 | { | 469 | { |
466 | struct resource_map *m, mm; | 470 | struct resource_map *m, mm; |
467 | struct socket_data *s_data = s->resource_data; | 471 | struct socket_data *s_data = s->resource_data; |
472 | unsigned long ok = 0; | ||
468 | 473 | ||
469 | for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) { | 474 | for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) { |
470 | mm = *m; | 475 | mm = *m; |
471 | do_mem_probe(mm.base, mm.num, s); | 476 | ok += do_mem_probe(mm.base, mm.num, s); |
472 | } | 477 | } |
478 | if (ok > 0) | ||
479 | return 0; | ||
480 | return -ENODEV; | ||
473 | } | 481 | } |
474 | 482 | ||
475 | #endif /* CONFIG_PCMCIA_PROBE */ | 483 | #endif /* CONFIG_PCMCIA_PROBE */ |
@@ -478,27 +486,30 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) | |||
478 | /* | 486 | /* |
479 | * Locking note: Must be called with skt_sem held! | 487 | * Locking note: Must be called with skt_sem held! |
480 | */ | 488 | */ |
481 | static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s) | 489 | static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s) |
482 | { | 490 | { |
483 | struct socket_data *s_data = s->resource_data; | 491 | struct socket_data *s_data = s->resource_data; |
484 | if (probe_mem) { | 492 | unsigned int probe_mask = MEM_PROBE_LOW; |
485 | unsigned int probe_mask; | 493 | int ret = 0; |
486 | 494 | ||
487 | down(&rsrc_sem); | 495 | if (!probe_mem) |
496 | return 0; | ||
488 | 497 | ||
489 | probe_mask = MEM_PROBE_LOW; | 498 | down(&rsrc_sem); |
490 | if (s->features & SS_CAP_PAGE_REGS) | ||
491 | probe_mask = MEM_PROBE_HIGH; | ||
492 | 499 | ||
493 | if (probe_mask & ~s_data->rsrc_mem_probe) { | 500 | if (s->features & SS_CAP_PAGE_REGS) |
501 | probe_mask = MEM_PROBE_HIGH; | ||
502 | |||
503 | if (probe_mask & ~s_data->rsrc_mem_probe) { | ||
504 | if (s->state & SOCKET_PRESENT) | ||
505 | ret = validate_mem(s, probe_mask); | ||
506 | if (!ret) | ||
494 | s_data->rsrc_mem_probe |= probe_mask; | 507 | s_data->rsrc_mem_probe |= probe_mask; |
508 | } | ||
495 | 509 | ||
496 | if (s->state & SOCKET_PRESENT) | 510 | up(&rsrc_sem); |
497 | validate_mem(s, probe_mask); | ||
498 | } | ||
499 | 511 | ||
500 | up(&rsrc_sem); | 512 | return ret; |
501 | } | ||
502 | } | 513 | } |
503 | 514 | ||
504 | struct pcmcia_align_data { | 515 | struct pcmcia_align_data { |
@@ -837,10 +848,9 @@ static int nonstatic_init(struct pcmcia_socket *s) | |||
837 | { | 848 | { |
838 | struct socket_data *data; | 849 | struct socket_data *data; |
839 | 850 | ||
840 | data = kmalloc(sizeof(struct socket_data), GFP_KERNEL); | 851 | data = kzalloc(sizeof(struct socket_data), GFP_KERNEL); |
841 | if (!data) | 852 | if (!data) |
842 | return -ENOMEM; | 853 | return -ENOMEM; |
843 | memset(data, 0, sizeof(struct socket_data)); | ||
844 | 854 | ||
845 | data->mem_db.next = &data->mem_db; | 855 | data->mem_db.next = &data->mem_db; |
846 | data->io_db.next = &data->io_db; | 856 | data->io_db.next = &data->io_db; |