aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2010-02-17 10:25:53 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2010-02-25 17:07:47 -0500
commit7b4884ca8853a638df0eb5d251d80d67777b8b1a (patch)
tree86cdd0c56a511c5ae4af132ba31c6fab58ee4ee3 /drivers/pcmcia
parentf309cb3e4fe79a68cb2fdedfb8a8a950a2cfe490 (diff)
pcmcia: validate late-added resources
Currently, only those mem resources are validated which are already registered at the time the first PCMCIA card is inserted. As we can only validate resources immediately after card insert, store "registered" mem resources in mem_db, and only upon validation move them to mem_db_valid. When allocationg mem resources, mem_db_valid is then preferred to mem_db. Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia')
-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;