aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/shpchp_pci.c
diff options
context:
space:
mode:
authorrajesh.shah@intel.com <rajesh.shah@intel.com>2005-10-13 15:05:36 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 18:36:59 -0400
commitdbd7a78818d125a0ebd5507d4edb4dd5900006ab (patch)
tree682a1681aad47f70bfb760fca077f54589be92c6 /drivers/pci/hotplug/shpchp_pci.c
parente3b1bd572f1cdb247bb4266a593b6894dc578d6a (diff)
[PATCH] shpchp: use the PCI core for hotplug resource management
This patch converts the standard hotplug controller driver to use the PCI core for resource management. This eliminates a whole lot of duplicated code, and integrates shpchp in the system's normal PCI handling code. Signed-off-by: Rajesh Shah <rajesh.shah@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/hotplug/shpchp_pci.c')
-rw-r--r--drivers/pci/hotplug/shpchp_pci.c482
1 files changed, 53 insertions, 429 deletions
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
index d867099114ec..89e404805777 100644
--- a/drivers/pci/hotplug/shpchp_pci.c
+++ b/drivers/pci/hotplug/shpchp_pci.c
@@ -37,46 +37,69 @@
37#include <linux/pci.h> 37#include <linux/pci.h>
38#include "../pci.h" 38#include "../pci.h"
39#include "shpchp.h" 39#include "shpchp.h"
40#ifndef CONFIG_IA64
41#include "../../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependant we are... */
42#endif
43 40
44int shpchp_configure_device (struct controller* ctrl, struct pci_func* func) 41int shpchp_configure_device(struct slot *p_slot)
45{ 42{
46 unsigned char bus; 43 struct pci_dev *dev;
47 struct pci_bus *child; 44 struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
48 int num; 45 int num, fn;
49 46
50 if (func->pci_dev == NULL) 47 dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0));
51 func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function)); 48 if (dev) {
52 49 err("Device %s already exists at %x:%x, cannot hot-add\n",
53 /* Still NULL ? Well then scan for it ! */ 50 pci_name(dev), p_slot->bus, p_slot->device);
54 if (func->pci_dev == NULL) { 51 return -EINVAL;
55 num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function));
56 if (num) {
57 dbg("%s: subordiante %p number %x\n", __FUNCTION__, ctrl->pci_dev->subordinate,
58 ctrl->pci_dev->subordinate->number);
59 pci_bus_add_devices(ctrl->pci_dev->subordinate);
60 }
61
62 func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
63 if (func->pci_dev == NULL) {
64 dbg("ERROR: pci_dev still null\n");
65 return 0;
66 }
67 } 52 }
68 53
69 if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { 54 num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));
70 pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus); 55 if (num == 0) {
71 child = pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); 56 err("No new device found\n");
72 pci_do_scan_bus(child); 57 return -ENODEV;
58 }
73 59
60 for (fn = 0; fn < 8; fn++) {
61 if (!(dev = pci_find_slot(p_slot->bus,
62 PCI_DEVFN(p_slot->device, fn))))
63 continue;
64 if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
65 err("Cannot hot-add display device %s\n",
66 pci_name(dev));
67 continue;
68 }
69 if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
70 (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
71 /* Find an unused bus number for the new bridge */
72 struct pci_bus *child;
73 unsigned char busnr, start = parent->secondary;
74 unsigned char end = parent->subordinate;
75 for (busnr = start; busnr <= end; busnr++) {
76 if (!pci_find_bus(pci_domain_nr(parent),
77 busnr))
78 break;
79 }
80 if (busnr >= end) {
81 err("No free bus for hot-added bridge\n");
82 continue;
83 }
84 child = pci_add_new_bus(parent, dev, busnr);
85 if (!child) {
86 err("Cannot add new bus for %s\n",
87 pci_name(dev));
88 continue;
89 }
90 child->subordinate = pci_do_scan_bus(child);
91 pci_bus_size_bridges(child);
92 }
93 /* TBD: program firmware provided _HPP values */
94 /* program_fw_provided_values(dev); */
74 } 95 }
75 96
97 pci_bus_assign_resources(parent);
98 pci_bus_add_devices(parent);
99 pci_enable_bridges(parent);
76 return 0; 100 return 0;
77} 101}
78 102
79
80int shpchp_unconfigure_device(struct pci_func* func) 103int shpchp_unconfigure_device(struct pci_func* func)
81{ 104{
82 int rc = 0; 105 int rc = 0;
@@ -95,44 +118,6 @@ int shpchp_unconfigure_device(struct pci_func* func)
95 return rc; 118 return rc;
96} 119}
97 120
98/*
99 * shpchp_set_irq
100 *
101 * @bus_num: bus number of PCI device
102 * @dev_num: device number of PCI device
103 * @slot: pointer to u8 where slot number will be returned
104 */
105int shpchp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
106{
107#if defined(CONFIG_X86) && !defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_64)
108 int rc;
109 u16 temp_word;
110 struct pci_dev fakedev;
111 struct pci_bus fakebus;
112
113 fakedev.devfn = dev_num << 3;
114 fakedev.bus = &fakebus;
115 fakebus.number = bus_num;
116 dbg("%s: dev %d, bus %d, pin %d, num %d\n",
117 __FUNCTION__, dev_num, bus_num, int_pin, irq_num);
118 rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num);
119 dbg("%s: rc %d\n", __FUNCTION__, rc);
120 if (!rc)
121 return !rc;
122
123 /* set the Edge Level Control Register (ELCR) */
124 temp_word = inb(0x4d0);
125 temp_word |= inb(0x4d1) << 8;
126
127 temp_word |= 0x01 << irq_num;
128
129 /* This should only be for x86 as it sets the Edge Level Control Register */
130 outb((u8) (temp_word & 0xFF), 0x4d0);
131 outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
132#endif
133 return 0;
134}
135
136/* More PCI configuration routines; this time centered around hotplug controller */ 121/* More PCI configuration routines; this time centered around hotplug controller */
137 122
138 123
@@ -447,364 +432,3 @@ int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot)
447 return 0; 432 return 0;
448} 433}
449 434
450
451/*
452 * shpchp_save_used_resources
453 *
454 * Stores used resource information for existing boards. this is
455 * for boards that were in the system when this driver was loaded.
456 * this function is for hot plug ADD
457 *
458 * returns 0 if success
459 * if disable == 1(DISABLE_CARD),
460 * it loops for all functions of the slot and disables them.
461 * else, it just get resources of the function and return.
462 */
463int shpchp_save_used_resources(struct controller *ctrl, struct pci_func *func, int disable)
464{
465 u8 cloop;
466 u8 header_type;
467 u8 secondary_bus;
468 u8 temp_byte;
469 u16 command;
470 u16 save_command;
471 u16 w_base, w_length;
472 u32 temp_register;
473 u32 save_base;
474 u32 base, length;
475 u64 base64 = 0;
476 int index = 0;
477 unsigned int devfn;
478 struct pci_resource *mem_node = NULL;
479 struct pci_resource *p_mem_node = NULL;
480 struct pci_resource *t_mem_node;
481 struct pci_resource *io_node;
482 struct pci_resource *bus_node;
483 struct pci_bus lpci_bus, *pci_bus;
484 memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
485 pci_bus = &lpci_bus;
486
487 if (disable)
488 func = shpchp_slot_find(func->bus, func->device, index++);
489
490 while ((func != NULL) && func->is_a_board) {
491 pci_bus->number = func->bus;
492 devfn = PCI_DEVFN(func->device, func->function);
493
494 /* Save the command register */
495 pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command);
496
497 if (disable) {
498 /* disable card */
499 command = 0x00;
500 pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
501 }
502
503 /* Check for Bridge */
504 pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
505
506 if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
507 dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n",
508 func->bus, func->device, save_command);
509 if (disable) {
510 /* Clear Bridge Control Register */
511 command = 0x00;
512 pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
513 }
514
515 pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
516 pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);
517
518 bus_node = kmalloc(sizeof(struct pci_resource),
519 GFP_KERNEL);
520 if (!bus_node)
521 return -ENOMEM;
522
523 bus_node->base = (ulong)secondary_bus;
524 bus_node->length = (ulong)(temp_byte - secondary_bus + 1);
525
526 bus_node->next = func->bus_head;
527 func->bus_head = bus_node;
528
529 /* Save IO base and Limit registers */
530 pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &temp_byte);
531 base = temp_byte;
532 pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &temp_byte);
533 length = temp_byte;
534
535 if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) {
536 io_node = kmalloc(sizeof(struct pci_resource),
537 GFP_KERNEL);
538 if (!io_node)
539 return -ENOMEM;
540
541 io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8;
542 io_node->length = (ulong)(length - base + 0x10) << 8;
543
544 io_node->next = func->io_head;
545 func->io_head = io_node;
546 }
547
548 /* Save memory base and Limit registers */
549 pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
550 pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
551
552 if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
553 mem_node = kmalloc(sizeof(struct pci_resource),
554 GFP_KERNEL);
555 if (!mem_node)
556 return -ENOMEM;
557
558 mem_node->base = (ulong)w_base << 16;
559 mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
560
561 mem_node->next = func->mem_head;
562 func->mem_head = mem_node;
563 }
564 /* Save prefetchable memory base and Limit registers */
565 pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
566 pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
567
568 if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
569 p_mem_node = kmalloc(sizeof(struct pci_resource),
570 GFP_KERNEL);
571 if (!p_mem_node)
572 return -ENOMEM;
573
574 p_mem_node->base = (ulong)w_base << 16;
575 p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
576
577 p_mem_node->next = func->p_mem_head;
578 func->p_mem_head = p_mem_node;
579 }
580 } else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
581 dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n",
582 func->bus, func->device, save_command);
583
584 /* Figure out IO and memory base lengths */
585 for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
586 pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base);
587
588 temp_register = 0xFFFFFFFF;
589 pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
590 pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
591
592 if (!disable)
593 pci_bus_write_config_dword(pci_bus, devfn, cloop, save_base);
594
595 if (!temp_register)
596 continue;
597
598 base = temp_register;
599
600 if ((base & PCI_BASE_ADDRESS_SPACE_IO) &&
601 (!disable || (save_command & PCI_COMMAND_IO))) {
602 /* IO base */
603 /* set temp_register = amount of IO space requested */
604 base = base & 0xFFFFFFFCL;
605 base = (~base) + 1;
606
607 io_node = kmalloc(sizeof (struct pci_resource),
608 GFP_KERNEL);
609 if (!io_node)
610 return -ENOMEM;
611
612 io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK;
613 io_node->length = (ulong)base;
614 dbg("sur adapter: IO bar=0x%x(length=0x%x)\n",
615 io_node->base, io_node->length);
616
617 io_node->next = func->io_head;
618 func->io_head = io_node;
619 } else { /* map Memory */
620 int prefetchable = 1;
621 /* struct pci_resources **res_node; */
622 char *res_type_str = "PMEM";
623 u32 temp_register2;
624
625 t_mem_node = kmalloc(sizeof (struct pci_resource),
626 GFP_KERNEL);
627 if (!t_mem_node)
628 return -ENOMEM;
629
630 if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
631 (!disable || (save_command & PCI_COMMAND_MEMORY))) {
632 prefetchable = 0;
633 mem_node = t_mem_node;
634 res_type_str++;
635 } else
636 p_mem_node = t_mem_node;
637
638 base = base & 0xFFFFFFF0L;
639 base = (~base) + 1;
640
641 switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
642 case PCI_BASE_ADDRESS_MEM_TYPE_32:
643 if (prefetchable) {
644 p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
645 p_mem_node->length = (ulong)base;
646 dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
647 res_type_str,
648 p_mem_node->base,
649 p_mem_node->length);
650
651 p_mem_node->next = func->p_mem_head;
652 func->p_mem_head = p_mem_node;
653 } else {
654 mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
655 mem_node->length = (ulong)base;
656 dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
657 res_type_str,
658 mem_node->base,
659 mem_node->length);
660
661 mem_node->next = func->mem_head;
662 func->mem_head = mem_node;
663 }
664 break;
665 case PCI_BASE_ADDRESS_MEM_TYPE_64:
666 pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
667 base64 = temp_register2;
668 base64 = (base64 << 32) | save_base;
669
670 if (temp_register2) {
671 dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n",
672 res_type_str, temp_register2, (u32)base64);
673 base64 &= 0x00000000FFFFFFFFL;
674 }
675
676 if (prefetchable) {
677 p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
678 p_mem_node->length = base;
679 dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
680 res_type_str,
681 p_mem_node->base,
682 p_mem_node->length);
683
684 p_mem_node->next = func->p_mem_head;
685 func->p_mem_head = p_mem_node;
686 } else {
687 mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
688 mem_node->length = base;
689 dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
690 res_type_str,
691 mem_node->base,
692 mem_node->length);
693
694 mem_node->next = func->mem_head;
695 func->mem_head = mem_node;
696 }
697 cloop += 4;
698 break;
699 default:
700 dbg("asur: reserved BAR type=0x%x\n",
701 temp_register);
702 break;
703 }
704 }
705 } /* End of base register loop */
706 } else { /* Some other unknown header type */
707 dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n",
708 func->bus, func->device);
709 }
710
711 /* find the next device in this slot */
712 if (!disable)
713 break;
714 func = shpchp_slot_find(func->bus, func->device, index++);
715 }
716
717 return 0;
718}
719
720/**
721 * kfree_resource_list: release memory of all list members
722 * @res: resource list to free
723 */
724static inline void
725return_resource_list(struct pci_resource **func, struct pci_resource **res)
726{
727 struct pci_resource *node;
728 struct pci_resource *t_node;
729
730 node = *func;
731 *func = NULL;
732 while (node) {
733 t_node = node->next;
734 return_resource(res, node);
735 node = t_node;
736 }
737}
738
739/*
740 * shpchp_return_board_resources
741 *
742 * this routine returns all resources allocated to a board to
743 * the available pool.
744 *
745 * returns 0 if success
746 */
747int shpchp_return_board_resources(struct pci_func * func,
748 struct resource_lists * resources)
749{
750 int rc;
751 dbg("%s\n", __FUNCTION__);
752
753 if (!func)
754 return 1;
755
756 return_resource_list(&(func->io_head),&(resources->io_head));
757 return_resource_list(&(func->mem_head),&(resources->mem_head));
758 return_resource_list(&(func->p_mem_head),&(resources->p_mem_head));
759 return_resource_list(&(func->bus_head),&(resources->bus_head));
760
761 rc = shpchp_resource_sort_and_combine(&(resources->mem_head));
762 rc |= shpchp_resource_sort_and_combine(&(resources->p_mem_head));
763 rc |= shpchp_resource_sort_and_combine(&(resources->io_head));
764 rc |= shpchp_resource_sort_and_combine(&(resources->bus_head));
765
766 return rc;
767}
768
769/**
770 * kfree_resource_list: release memory of all list members
771 * @res: resource list to free
772 */
773static inline void
774kfree_resource_list(struct pci_resource **r)
775{
776 struct pci_resource *res, *tres;
777
778 res = *r;
779 *r = NULL;
780
781 while (res) {
782 tres = res;
783 res = res->next;
784 kfree(tres);
785 }
786}
787
788/**
789 * shpchp_destroy_resource_list: put node back in the resource list
790 * @resources: list to put nodes back
791 */
792void shpchp_destroy_resource_list(struct resource_lists *resources)
793{
794 kfree_resource_list(&(resources->io_head));
795 kfree_resource_list(&(resources->mem_head));
796 kfree_resource_list(&(resources->p_mem_head));
797 kfree_resource_list(&(resources->bus_head));
798}
799
800/**
801 * shpchp_destroy_board_resources: put node back in the resource list
802 * @resources: list to put nodes back
803 */
804void shpchp_destroy_board_resources(struct pci_func * func)
805{
806 kfree_resource_list(&(func->io_head));
807 kfree_resource_list(&(func->mem_head));
808 kfree_resource_list(&(func->p_mem_head));
809 kfree_resource_list(&(func->bus_head));
810}