aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r--drivers/pcmcia/cs_internal.h2
-rw-r--r--drivers/pcmcia/ds.c4
-rw-r--r--drivers/pcmcia/rsrc_mgr.c6
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c123
4 files changed, 74 insertions, 61 deletions
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 55867bc7f199..634426b78f2c 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -117,7 +117,7 @@ int verify_cis_cache(struct pcmcia_socket *s);
117int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse); 117int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse);
118 118
119/* In rsrc_mgr */ 119/* In rsrc_mgr */
120void pcmcia_validate_mem(struct pcmcia_socket *s); 120int pcmcia_validate_mem(struct pcmcia_socket *s);
121struct resource *pcmcia_find_io_region(unsigned long base, int num, unsigned long align, 121struct resource *pcmcia_find_io_region(unsigned long base, int num, unsigned long align,
122 struct pcmcia_socket *s); 122 struct pcmcia_socket *s);
123int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start, 123int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start,
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 6fb76399547e..b120794c03a9 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -583,7 +583,9 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
583 if (!(s->resource_setup_done)) 583 if (!(s->resource_setup_done))
584 return -EAGAIN; /* try again, but later... */ 584 return -EAGAIN; /* try again, but later... */
585 585
586 pcmcia_validate_mem(s); 586 if (pcmcia_validate_mem(s))
587 return -EAGAIN; /* try again, but later... */
588
587 ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo); 589 ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo);
588 if (ret || !cisinfo.Chains) { 590 if (ret || !cisinfo.Chains) {
589 ds_dbg(0, "invalid CIS or invalid resources\n"); 591 ds_dbg(0, "invalid CIS or invalid resources\n");
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 0668384ebc8b..b02598a5a912 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -98,10 +98,12 @@ int pcmcia_adjust_resource_info(adjust_t *adj)
98} 98}
99EXPORT_SYMBOL(pcmcia_adjust_resource_info); 99EXPORT_SYMBOL(pcmcia_adjust_resource_info);
100 100
101void pcmcia_validate_mem(struct pcmcia_socket *s) 101int pcmcia_validate_mem(struct pcmcia_socket *s)
102{ 102{
103 if (s->resource_ops->validate_mem) 103 if (s->resource_ops->validate_mem)
104 s->resource_ops->validate_mem(s); 104 return s->resource_ops->validate_mem(s);
105 /* if there is no callback, we can assume that everything is OK */
106 return 0;
105} 107}
106EXPORT_SYMBOL(pcmcia_validate_mem); 108EXPORT_SYMBOL(pcmcia_validate_mem);
107 109
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 00960a379b9c..ebfcab5df9ea 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -407,56 +407,62 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
407 407
408static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s) 408static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
409{ 409{
410 struct socket_data *s_data = s->resource_data; 410 struct socket_data *s_data = s->resource_data;
411 u_long ok; 411 u_long ok;
412 if (m == &s_data->mem_db) 412 if (m == &s_data->mem_db)
413 return 0; 413 return 0;
414 ok = inv_probe(m->next, s); 414 ok = inv_probe(m->next, s);
415 if (ok) { 415 if (ok) {
416 if (m->base >= 0x100000) 416 if (m->base >= 0x100000)
417 sub_interval(&s_data->mem_db, m->base, m->num); 417 sub_interval(&s_data->mem_db, m->base, m->num);
418 return ok; 418 return ok;
419 } 419 }
420 if (m->base < 0x100000) 420 if (m->base < 0x100000)
421 return 0; 421 return 0;
422 return do_mem_probe(m->base, m->num, s); 422 return do_mem_probe(m->base, m->num, s);
423} 423}
424 424
425static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) 425static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
426{ 426{
427 struct resource_map *m, mm; 427 struct resource_map *m, mm;
428 static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 }; 428 static unsigned char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
429 u_long b, i, ok = 0; 429 unsigned long b, i, ok = 0;
430 struct socket_data *s_data = s->resource_data; 430 struct socket_data *s_data = s->resource_data;
431 431
432 /* We do up to four passes through the list */ 432 /* We do up to four passes through the list */
433 if (probe_mask & MEM_PROBE_HIGH) { 433 if (probe_mask & MEM_PROBE_HIGH) {
434 if (inv_probe(s_data->mem_db.next, s) > 0) 434 if (inv_probe(s_data->mem_db.next, s) > 0)
435 return; 435 return 0;
436 printk(KERN_NOTICE "cs: warning: no high memory space " 436 printk(KERN_NOTICE "cs: warning: no high memory space "
437 "available!\n"); 437 "available!\n");
438 } 438 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 } 439 }
449 /* Special probe for 64K-aligned block */ 440
450 for (i = 0; i < 4; i++) { 441 for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
451 b = order[i] << 12; 442 mm = *m;
452 if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) { 443 /* Only probe < 1 MB */
453 if (ok >= mem_limit) 444 if (mm.base >= 0x100000)
454 sub_interval(&s_data->mem_db, b, 0x10000); 445 continue;
455 else 446 if ((mm.base | mm.num) & 0xffff) {
456 ok += do_mem_probe(b, 0x10000, s); 447 ok += do_mem_probe(mm.base, mm.num, s);
457 } 448 continue;
449 }
450 /* Special probe for 64K-aligned block */
451 for (i = 0; i < 4; i++) {
452 b = order[i] << 12;
453 if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
454 if (ok >= mem_limit)
455 sub_interval(&s_data->mem_db, b, 0x10000);
456 else
457 ok += do_mem_probe(b, 0x10000, s);
458 }
459 }
458 } 460 }
459 } 461
462 if (ok > 0)
463 return 0;
464
465 return -ENODEV;
460} 466}
461 467
462#else /* CONFIG_PCMCIA_PROBE */ 468#else /* CONFIG_PCMCIA_PROBE */
@@ -478,27 +484,30 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
478/* 484/*
479 * Locking note: Must be called with skt_sem held! 485 * Locking note: Must be called with skt_sem held!
480 */ 486 */
481static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s) 487static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
482{ 488{
483 struct socket_data *s_data = s->resource_data; 489 struct socket_data *s_data = s->resource_data;
484 if (probe_mem) { 490 unsigned int probe_mask = MEM_PROBE_LOW;
485 unsigned int probe_mask; 491 int ret = 0;
486 492
487 down(&rsrc_sem); 493 if (!probe_mem)
494 return 0;
488 495
489 probe_mask = MEM_PROBE_LOW; 496 down(&rsrc_sem);
490 if (s->features & SS_CAP_PAGE_REGS)
491 probe_mask = MEM_PROBE_HIGH;
492 497
493 if (probe_mask & ~s_data->rsrc_mem_probe) { 498 if (s->features & SS_CAP_PAGE_REGS)
499 probe_mask = MEM_PROBE_HIGH;
500
501 if (probe_mask & ~s_data->rsrc_mem_probe) {
502 if (s->state & SOCKET_PRESENT)
503 ret = validate_mem(s, probe_mask);
504 if (!ret)
494 s_data->rsrc_mem_probe |= probe_mask; 505 s_data->rsrc_mem_probe |= probe_mask;
506 }
495 507
496 if (s->state & SOCKET_PRESENT) 508 up(&rsrc_sem);
497 validate_mem(s, probe_mask);
498 }
499 509
500 up(&rsrc_sem); 510 return ret;
501 }
502} 511}
503 512
504struct pcmcia_align_data { 513struct pcmcia_align_data {