aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c67
1 files changed, 48 insertions, 19 deletions
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index a06881c3b962..a69eed6c5b92 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -55,8 +55,8 @@ struct resource_map {
55 55
56struct socket_data { 56struct socket_data {
57 struct resource_map mem_db; 57 struct resource_map mem_db;
58 struct resource_map mem_db_valid;
58 struct resource_map io_db; 59 struct resource_map io_db;
59 unsigned int rsrc_mem_probe;
60}; 60};
61 61
62#define MEM_PROBE_LOW (1 << 0) 62#define MEM_PROBE_LOW (1 << 0)
@@ -357,6 +357,7 @@ static int do_validate_mem(struct pcmcia_socket *s,
357 struct resource *res, 357 struct resource *res,
358 unsigned int *value)) 358 unsigned int *value))
359{ 359{
360 struct socket_data *s_data = s->resource_data;
360 struct resource *res1, *res2; 361 struct resource *res1, *res2;
361 unsigned int info1 = 1, info2 = 1; 362 unsigned int info1 = 1, info2 = 1;
362 int ret = -EINVAL; 363 int ret = -EINVAL;
@@ -382,6 +383,12 @@ static int do_validate_mem(struct pcmcia_socket *s,
382 if ((ret) || (info1 != info2) || (info1 == 0)) 383 if ((ret) || (info1 != info2) || (info1 == 0))
383 return -EINVAL; 384 return -EINVAL;
384 385
386 if (validate && !s->fake_cis) {
387 /* move it to the validated data set */
388 add_interval(&s_data->mem_db_valid, base, size);
389 sub_interval(&s_data->mem_db, base, size);
390 }
391
385 return 0; 392 return 0;
386} 393}
387 394
@@ -491,6 +498,8 @@ static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
491 if (probe_mask & MEM_PROBE_HIGH) { 498 if (probe_mask & MEM_PROBE_HIGH) {
492 if (inv_probe(s_data->mem_db.next, s) > 0) 499 if (inv_probe(s_data->mem_db.next, s) > 0)
493 return 0; 500 return 0;
501 if (s_data->mem_db_valid.next != &s_data->mem_db_valid)
502 return 0;
494 dev_printk(KERN_NOTICE, &s->dev, 503 dev_printk(KERN_NOTICE, &s->dev,
495 "cs: warning: no high memory space available!\n"); 504 "cs: warning: no high memory space available!\n");
496 return -ENODEV; 505 return -ENODEV;
@@ -565,21 +574,18 @@ static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
565{ 574{
566 struct socket_data *s_data = s->resource_data; 575 struct socket_data *s_data = s->resource_data;
567 unsigned int probe_mask = MEM_PROBE_LOW; 576 unsigned int probe_mask = MEM_PROBE_LOW;
568 int ret = 0; 577 int ret;
569 578
570 if (!probe_mem) 579 if (!probe_mem || !(s->state & SOCKET_PRESENT))
571 return 0; 580 return 0;
572 581
573 if (s->features & SS_CAP_PAGE_REGS) 582 if (s->features & SS_CAP_PAGE_REGS)
574 probe_mask = MEM_PROBE_HIGH; 583 probe_mask = MEM_PROBE_HIGH;
575 584
576 if (probe_mask & ~s_data->rsrc_mem_probe) { 585 ret = validate_mem(s, probe_mask);
577 if (s->state & SOCKET_PRESENT) { 586
578 ret = validate_mem(s, probe_mask); 587 if (s_data->mem_db_valid.next != &s_data->mem_db_valid)
579 if (!ret) 588 return 0;
580 s_data->rsrc_mem_probe |= probe_mask;
581 }
582 }
583 589
584 return ret; 590 return ret;
585} 591}
@@ -723,15 +729,15 @@ static struct resource *nonstatic_find_mem_region(u_long base, u_long num,
723 struct socket_data *s_data = s->resource_data; 729 struct socket_data *s_data = s->resource_data;
724 struct pcmcia_align_data data; 730 struct pcmcia_align_data data;
725 unsigned long min, max; 731 unsigned long min, max;
726 int ret, i; 732 int ret, i, j;
727 733
728 low = low || !(s->features & SS_CAP_PAGE_REGS); 734 low = low || !(s->features & SS_CAP_PAGE_REGS);
729 735
730 data.mask = align - 1; 736 data.mask = align - 1;
731 data.offset = base & data.mask; 737 data.offset = base & data.mask;
732 data.map = &s_data->mem_db;
733 738
734 for (i = 0; i < 2; i++) { 739 for (i = 0; i < 2; i++) {
740 data.map = &s_data->mem_db_valid;
735 if (low) { 741 if (low) {
736 max = 0x100000UL; 742 max = 0x100000UL;
737 min = base < max ? base : 0; 743 min = base < max ? base : 0;
@@ -740,15 +746,23 @@ static struct resource *nonstatic_find_mem_region(u_long base, u_long num,
740 min = 0x100000UL + base; 746 min = 0x100000UL + base;
741 } 747 }
742 748
749 for (j = 0; j < 2; j++) {
743#ifdef CONFIG_PCI 750#ifdef CONFIG_PCI
744 if (s->cb_dev) { 751 if (s->cb_dev) {
745 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 752 ret = pci_bus_alloc_resource(s->cb_dev->bus,
746 1, min, 0, 753 res, num, 1, min, 0,
747 pcmcia_align, &data); 754 pcmcia_align, &data);
748 } else 755 } else
749#endif 756#endif
750 ret = allocate_resource(&iomem_resource, res, num, min, 757 {
751 max, 1, pcmcia_align, &data); 758 ret = allocate_resource(&iomem_resource,
759 res, num, min, max, 1,
760 pcmcia_align, &data);
761 }
762 if (ret == 0)
763 break;
764 data.map = &s_data->mem_db;
765 }
752 if (ret == 0 || low) 766 if (ret == 0 || low)
753 break; 767 break;
754 low = 1; 768 low = 1;
@@ -901,6 +915,7 @@ static int nonstatic_init(struct pcmcia_socket *s)
901 return -ENOMEM; 915 return -ENOMEM;
902 916
903 data->mem_db.next = &data->mem_db; 917 data->mem_db.next = &data->mem_db;
918 data->mem_db_valid.next = &data->mem_db_valid;
904 data->io_db.next = &data->io_db; 919 data->io_db.next = &data->io_db;
905 920
906 s->resource_data = (void *) data; 921 s->resource_data = (void *) data;
@@ -915,6 +930,10 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s)
915 struct socket_data *data = s->resource_data; 930 struct socket_data *data = s->resource_data;
916 struct resource_map *p, *q; 931 struct resource_map *p, *q;
917 932
933 for (p = data->mem_db_valid.next; p != &data->mem_db_valid; p = q) {
934 q = p->next;
935 kfree(p);
936 }
918 for (p = data->mem_db.next; p != &data->mem_db; p = q) { 937 for (p = data->mem_db.next; p != &data->mem_db; p = q) {
919 q = p->next; 938 q = p->next;
920 kfree(p); 939 kfree(p);
@@ -1010,6 +1029,16 @@ static ssize_t show_mem_db(struct device *dev,
1010 mutex_lock(&s->ops_mutex); 1029 mutex_lock(&s->ops_mutex);
1011 data = s->resource_data; 1030 data = s->resource_data;
1012 1031
1032 for (p = data->mem_db_valid.next; p != &data->mem_db_valid;
1033 p = p->next) {
1034 if (ret > (PAGE_SIZE - 10))
1035 continue;
1036 ret += snprintf(&buf[ret], (PAGE_SIZE - ret - 1),
1037 "0x%08lx - 0x%08lx\n",
1038 ((unsigned long) p->base),
1039 ((unsigned long) p->base + p->num - 1));
1040 }
1041
1013 for (p = data->mem_db.next; p != &data->mem_db; p = p->next) { 1042 for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
1014 if (ret > (PAGE_SIZE - 10)) 1043 if (ret > (PAGE_SIZE - 10))
1015 continue; 1044 continue;