diff options
| -rw-r--r-- | drivers/pcmcia/rsrc_nonstatic.c | 67 |
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 | ||
| 56 | struct socket_data { | 56 | struct 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; |
