diff options
Diffstat (limited to 'drivers/pcmcia/yenta_socket.c')
-rw-r--r-- | drivers/pcmcia/yenta_socket.c | 160 |
1 files changed, 105 insertions, 55 deletions
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 15f716a7968a..6837491f021c 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c | |||
@@ -527,98 +527,144 @@ static int yenta_sock_suspend(struct pcmcia_socket *sock) | |||
527 | * Use an adaptive allocation for the memory resource, | 527 | * Use an adaptive allocation for the memory resource, |
528 | * sometimes the memory behind pci bridges is limited: | 528 | * sometimes the memory behind pci bridges is limited: |
529 | * 1/8 of the size of the io window of the parent. | 529 | * 1/8 of the size of the io window of the parent. |
530 | * max 4 MB, min 16 kB. | 530 | * max 4 MB, min 16 kB. We try very hard to not get below |
531 | * the "ACC" values, though. | ||
531 | */ | 532 | */ |
532 | #define BRIDGE_MEM_MAX 4*1024*1024 | 533 | #define BRIDGE_MEM_MAX 4*1024*1024 |
534 | #define BRIDGE_MEM_ACC 128*1024 | ||
533 | #define BRIDGE_MEM_MIN 16*1024 | 535 | #define BRIDGE_MEM_MIN 16*1024 |
534 | 536 | ||
535 | #define BRIDGE_IO_MAX 256 | 537 | #define BRIDGE_IO_MAX 512 |
538 | #define BRIDGE_IO_ACC 256 | ||
536 | #define BRIDGE_IO_MIN 32 | 539 | #define BRIDGE_IO_MIN 32 |
537 | 540 | ||
538 | #ifndef PCIBIOS_MIN_CARDBUS_IO | 541 | #ifndef PCIBIOS_MIN_CARDBUS_IO |
539 | #define PCIBIOS_MIN_CARDBUS_IO PCIBIOS_MIN_IO | 542 | #define PCIBIOS_MIN_CARDBUS_IO PCIBIOS_MIN_IO |
540 | #endif | 543 | #endif |
541 | 544 | ||
542 | static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type) | 545 | static int yenta_search_one_res(struct resource *root, struct resource *res, |
546 | u32 min) | ||
547 | { | ||
548 | u32 align, size, start, end; | ||
549 | |||
550 | if (res->flags & IORESOURCE_IO) { | ||
551 | align = 1024; | ||
552 | size = BRIDGE_IO_MAX; | ||
553 | start = PCIBIOS_MIN_CARDBUS_IO; | ||
554 | end = ~0U; | ||
555 | } else { | ||
556 | unsigned long avail = root->end - root->start; | ||
557 | int i; | ||
558 | size = BRIDGE_MEM_MAX; | ||
559 | if (size > avail/8) { | ||
560 | size=(avail+1)/8; | ||
561 | /* round size down to next power of 2 */ | ||
562 | i = 0; | ||
563 | while ((size /= 2) != 0) | ||
564 | i++; | ||
565 | size = 1 << i; | ||
566 | } | ||
567 | if (size < min) | ||
568 | size = min; | ||
569 | align = size; | ||
570 | start = PCIBIOS_MIN_MEM; | ||
571 | end = ~0U; | ||
572 | } | ||
573 | |||
574 | do { | ||
575 | if (allocate_resource(root, res, size, start, end, align, | ||
576 | NULL, NULL)==0) { | ||
577 | return 1; | ||
578 | } | ||
579 | size = size/2; | ||
580 | align = size; | ||
581 | } while (size >= min); | ||
582 | |||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | |||
587 | static int yenta_search_res(struct yenta_socket *socket, struct resource *res, | ||
588 | u32 min) | ||
589 | { | ||
590 | int i; | ||
591 | for (i=0; i<PCI_BUS_NUM_RESOURCES; i++) { | ||
592 | struct resource * root = socket->dev->bus->resource[i]; | ||
593 | if (!root) | ||
594 | continue; | ||
595 | |||
596 | if ((res->flags ^ root->flags) & | ||
597 | (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH)) | ||
598 | continue; /* Wrong type */ | ||
599 | |||
600 | if (yenta_search_one_res(root, res, min)) | ||
601 | return 1; | ||
602 | } | ||
603 | return 0; | ||
604 | } | ||
605 | |||
606 | static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end) | ||
543 | { | 607 | { |
544 | struct pci_bus *bus; | 608 | struct pci_bus *bus; |
545 | struct resource *root, *res; | 609 | struct resource *root, *res; |
546 | u32 start, end; | 610 | u32 start, end; |
547 | u32 align, size, min; | ||
548 | unsigned offset; | ||
549 | unsigned mask; | 611 | unsigned mask; |
550 | 612 | ||
551 | res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; | 613 | res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; |
552 | /* Already allocated? */ | 614 | /* Already allocated? */ |
553 | if (res->parent) | 615 | if (res->parent) |
554 | return 0; | 616 | return; |
555 | 617 | ||
556 | /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ | 618 | /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ |
557 | mask = ~0xfff; | 619 | mask = ~0xfff; |
558 | if (type & IORESOURCE_IO) | 620 | if (type & IORESOURCE_IO) |
559 | mask = ~3; | 621 | mask = ~3; |
560 | 622 | ||
561 | offset = 0x1c + 8*nr; | ||
562 | bus = socket->dev->subordinate; | 623 | bus = socket->dev->subordinate; |
563 | res->name = bus->name; | 624 | res->name = bus->name; |
564 | res->flags = type; | 625 | res->flags = type; |
565 | res->start = 0; | ||
566 | res->end = 0; | ||
567 | root = pci_find_parent_resource(socket->dev, res); | ||
568 | 626 | ||
569 | if (!root) | 627 | start = config_readl(socket, addr_start) & mask; |
570 | return; | 628 | end = config_readl(socket, addr_end) | ~mask; |
571 | |||
572 | start = config_readl(socket, offset) & mask; | ||
573 | end = config_readl(socket, offset+4) | ~mask; | ||
574 | if (start && end > start && !override_bios) { | 629 | if (start && end > start && !override_bios) { |
575 | res->start = start; | 630 | res->start = start; |
576 | res->end = end; | 631 | res->end = end; |
577 | if (request_resource(root, res) == 0) | 632 | root = pci_find_parent_resource(socket->dev, res); |
633 | if (root && (request_resource(root, res) == 0)) | ||
578 | return; | 634 | return; |
579 | printk(KERN_INFO "yenta %s: Preassigned resource %d busy, reconfiguring...\n", | 635 | printk(KERN_INFO "yenta %s: Preassigned resource %d busy or not available, reconfiguring...\n", |
580 | pci_name(socket->dev), nr); | 636 | pci_name(socket->dev), nr); |
581 | res->start = res->end = 0; | ||
582 | } | 637 | } |
583 | 638 | ||
584 | if (type & IORESOURCE_IO) { | 639 | if (type & IORESOURCE_IO) { |
585 | align = 1024; | 640 | if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) || |
586 | size = BRIDGE_IO_MAX; | 641 | (yenta_search_res(socket, res, BRIDGE_IO_ACC)) || |
587 | min = BRIDGE_IO_MIN; | 642 | (yenta_search_res(socket, res, BRIDGE_IO_MIN))) { |
588 | start = PCIBIOS_MIN_CARDBUS_IO; | 643 | config_writel(socket, addr_start, res->start); |
589 | end = ~0U; | 644 | config_writel(socket, addr_end, res->end); |
645 | } | ||
590 | } else { | 646 | } else { |
591 | unsigned long avail = root->end - root->start; | 647 | if (type & IORESOURCE_PREFETCH) { |
592 | int i; | 648 | if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) || |
593 | size = BRIDGE_MEM_MAX; | 649 | (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || |
594 | if (size > avail/8) { | 650 | (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { |
595 | size=(avail+1)/8; | 651 | config_writel(socket, addr_start, res->start); |
596 | /* round size down to next power of 2 */ | 652 | config_writel(socket, addr_end, res->end); |
597 | i = 0; | 653 | } |
598 | while ((size /= 2) != 0) | 654 | /* Approximating prefetchable by non-prefetchable */ |
599 | i++; | 655 | res->flags = IORESOURCE_MEM; |
600 | size = 1 << i; | ||
601 | } | 656 | } |
602 | if (size < BRIDGE_MEM_MIN) | 657 | if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) || |
603 | size = BRIDGE_MEM_MIN; | 658 | (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || |
604 | min = BRIDGE_MEM_MIN; | 659 | (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { |
605 | align = size; | 660 | config_writel(socket, addr_start, res->start); |
606 | start = PCIBIOS_MIN_MEM; | 661 | config_writel(socket, addr_end, res->end); |
607 | end = ~0U; | ||
608 | } | ||
609 | |||
610 | do { | ||
611 | if (allocate_resource(root, res, size, start, end, align, NULL, NULL)==0) { | ||
612 | config_writel(socket, offset, res->start); | ||
613 | config_writel(socket, offset+4, res->end); | ||
614 | return; | ||
615 | } | 662 | } |
616 | size = size/2; | 663 | } |
617 | align = size; | 664 | |
618 | } while (size >= min); | ||
619 | printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n", | 665 | printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n", |
620 | pci_name(socket->dev), type); | 666 | pci_name(socket->dev), type); |
621 | res->start = res->end = 0; | 667 | res->start = res->end = res->flags = 0; |
622 | } | 668 | } |
623 | 669 | ||
624 | /* | 670 | /* |
@@ -626,10 +672,14 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ | |||
626 | */ | 672 | */ |
627 | static void yenta_allocate_resources(struct yenta_socket *socket) | 673 | static void yenta_allocate_resources(struct yenta_socket *socket) |
628 | { | 674 | { |
629 | yenta_allocate_res(socket, 0, IORESOURCE_MEM|IORESOURCE_PREFETCH); | 675 | yenta_allocate_res(socket, 0, IORESOURCE_IO, |
630 | yenta_allocate_res(socket, 1, IORESOURCE_MEM); | 676 | PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0); |
631 | yenta_allocate_res(socket, 2, IORESOURCE_IO); | 677 | yenta_allocate_res(socket, 1, IORESOURCE_IO, |
632 | yenta_allocate_res(socket, 3, IORESOURCE_IO); /* PCI isn't clever enough to use this one yet */ | 678 | PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1); |
679 | yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH, | ||
680 | PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0); | ||
681 | yenta_allocate_res(socket, 3, IORESOURCE_MEM, | ||
682 | PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1); | ||
633 | } | 683 | } |
634 | 684 | ||
635 | 685 | ||