aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2005-07-12 16:58:17 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-12 19:01:00 -0400
commiteb0a90b4970d667e9ae9df538710f12b8e78e442 (patch)
tree341f050368edbe235e3515032d5b6797545b7745 /drivers
parent278798357d4a8658067dc9ac399d8ffba8389f03 (diff)
[PATCH] yenta: allocate resource fixes
The current CardBus window allocation code in yenta_socket is unable to handle the transparent PCI-bridge handling update in 2.6.13. We need to check _all_ resources of a given type to find the best one suitable for CardBus windows, not just the first one. Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pcmcia/yenta_socket.c126
1 files changed, 88 insertions, 38 deletions
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index d3807e22fe04..f9d2367b6bdf 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -527,24 +527,87 @@ 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
545static 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
587static 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
542static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end) 606static 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 mask; 611 unsigned mask;
549 612
550 res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; 613 res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr;
@@ -573,48 +636,35 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
573 pci_name(socket->dev), nr); 636 pci_name(socket->dev), nr);
574 } 637 }
575 638
576 res->start = 0;
577 res->end = 0;
578 root = pci_find_parent_resource(socket->dev, res);
579
580 if (type & IORESOURCE_IO) { 639 if (type & IORESOURCE_IO) {
581 align = 1024; 640 if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) ||
582 size = BRIDGE_IO_MAX; 641 (yenta_search_res(socket, res, BRIDGE_IO_ACC)) ||
583 min = BRIDGE_IO_MIN; 642 (yenta_search_res(socket, res, BRIDGE_IO_MIN))) {
584 start = PCIBIOS_MIN_CARDBUS_IO; 643 config_writel(socket, addr_start, res->start);
585 end = ~0U; 644 config_writel(socket, addr_end, res->end);
645 }
586 } else { 646 } else {
587 unsigned long avail = root->end - root->start; 647 if (type & IORESOURCE_PREFETCH) {
588 int i; 648 if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||
589 size = BRIDGE_MEM_MAX; 649 (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) ||
590 if (size > avail/8) { 650 (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
591 size=(avail+1)/8; 651 config_writel(socket, addr_start, res->start);
592 /* round size down to next power of 2 */ 652 config_writel(socket, addr_end, res->end);
593 i = 0; 653 }
594 while ((size /= 2) != 0) 654 /* Approximating prefetchable by non-prefetchable */
595 i++; 655 res->flags = IORESOURCE_MEM;
596 size = 1 << i;
597 } 656 }
598 if (size < BRIDGE_MEM_MIN) 657 if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||
599 size = BRIDGE_MEM_MIN; 658 (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) ||
600 min = BRIDGE_MEM_MIN; 659 (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
601 align = size;
602 start = PCIBIOS_MIN_MEM;
603 end = ~0U;
604 }
605
606 do {
607 if (allocate_resource(root, res, size, start, end, align, NULL, NULL)==0) {
608 config_writel(socket, addr_start, res->start); 660 config_writel(socket, addr_start, res->start);
609 config_writel(socket, addr_end, res->end); 661 config_writel(socket, addr_end, res->end);
610 return;
611 } 662 }
612 size = size/2; 663 }
613 align = size; 664
614 } while (size >= min);
615 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",
616 pci_name(socket->dev), type); 666 pci_name(socket->dev), type);
617 res->start = res->end = 0; 667 res->start = res->end = res->flags = 0;
618} 668}
619 669
620/* 670/*