aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/rsrc_nonstatic.c
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2005-09-28 13:41:56 -0400
committerDominik Brodowski <linux@dominikbrodowski.net>2006-01-05 17:41:14 -0500
commitde75914ee103a30d82ad21b39b7e04f70e4fa1f0 (patch)
tree492f275d49d2e37449ba89594127ebca8502cb3f /drivers/pcmcia/rsrc_nonstatic.c
parent9da4bc6d6a38c1c3d850c046d0aee324c1a2e52a (diff)
[PATCH] pcmcia: validate_mem shouldn't be void
Add a return value to pcmcia_validate_mem. Only if we have enough memory available to map the CIS, we should proceed in trying to determine information about the device. Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia/rsrc_nonstatic.c')
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c123
1 files changed, 66 insertions, 57 deletions
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 {