aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/acpiphp_glue.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug/acpiphp_glue.c')
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c111
1 files changed, 109 insertions, 2 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 4e25d9c7cc39..fe0a6b7662f7 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -751,6 +751,106 @@ static int power_off_slot(struct acpiphp_slot *slot)
751} 751}
752 752
753 753
754
755/**
756 * acpiphp_max_busnr - return the highest reserved bus number under
757 * the given bus.
758 * @bus: bus to start search with
759 *
760 */
761static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
762{
763 struct list_head *tmp;
764 unsigned char max, n;
765
766 /*
767 * pci_bus_max_busnr will return the highest
768 * reserved busnr for all these children.
769 * that is equivalent to the bus->subordinate
770 * value. We don't want to use the parent's
771 * bus->subordinate value because it could have
772 * padding in it.
773 */
774 max = bus->secondary;
775
776 list_for_each(tmp, &bus->children) {
777 n = pci_bus_max_busnr(pci_bus_b(tmp));
778 if (n > max)
779 max = n;
780 }
781 return max;
782}
783
784
785
786/**
787 * get_func - get a pointer to acpiphp_func given a slot, device
788 * @slot: slot to search
789 * @dev: pci_dev struct to match.
790 *
791 * This function will increase the reference count of pci_dev,
792 * so callers should call pci_dev_put when complete.
793 *
794 */
795static struct acpiphp_func *
796get_func(struct acpiphp_slot *slot, struct pci_dev *dev)
797{
798 struct acpiphp_func *func = NULL;
799 struct pci_bus *bus = slot->bridge->pci_bus;
800 struct pci_dev *pdev;
801
802 list_for_each_entry(func, &slot->funcs, sibling) {
803 pdev = pci_get_slot(bus, PCI_DEVFN(slot->device,
804 func->function));
805 if (pdev) {
806 if (pdev == dev)
807 break;
808 pci_dev_put(pdev);
809 }
810 }
811 return func;
812}
813
814
815/**
816 * acpiphp_bus_add - add a new bus to acpi subsystem
817 * @func: acpiphp_func of the bridge
818 *
819 */
820static int acpiphp_bus_add(struct acpiphp_func *func)
821{
822 acpi_handle phandle;
823 struct acpi_device *device, *pdevice;
824 int ret_val;
825
826 acpi_get_parent(func->handle, &phandle);
827 if (acpi_bus_get_device(phandle, &pdevice)) {
828 dbg("no parent device, assuming NULL\n");
829 pdevice = NULL;
830 }
831 if (acpi_bus_get_device(func->handle, &device)) {
832 ret_val = acpi_bus_add(&device, pdevice, func->handle,
833 ACPI_BUS_TYPE_DEVICE);
834 if (ret_val) {
835 dbg("error adding bus, %x\n",
836 -ret_val);
837 goto acpiphp_bus_add_out;
838 }
839 }
840 /*
841 * try to start anyway. We could have failed to add
842 * simply because this bus had previously been added
843 * on another add. Don't bother with the return value
844 * we just keep going.
845 */
846 ret_val = acpi_bus_start(device);
847
848acpiphp_bus_add_out:
849 return ret_val;
850}
851
852
853
754/** 854/**
755 * enable_device - enable, configure a slot 855 * enable_device - enable, configure a slot
756 * @slot: slot to be enabled 856 * @slot: slot to be enabled
@@ -788,7 +888,7 @@ static int enable_device(struct acpiphp_slot *slot)
788 goto err_exit; 888 goto err_exit;
789 } 889 }
790 890
791 max = bus->secondary; 891 max = acpiphp_max_busnr(bus);
792 for (pass = 0; pass < 2; pass++) { 892 for (pass = 0; pass < 2; pass++) {
793 list_for_each_entry(dev, &bus->devices, bus_list) { 893 list_for_each_entry(dev, &bus->devices, bus_list) {
794 if (PCI_SLOT(dev->devfn) != slot->device) 894 if (PCI_SLOT(dev->devfn) != slot->device)
@@ -796,8 +896,15 @@ static int enable_device(struct acpiphp_slot *slot)
796 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || 896 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
797 dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { 897 dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
798 max = pci_scan_bridge(bus, dev, max, pass); 898 max = pci_scan_bridge(bus, dev, max, pass);
799 if (pass && dev->subordinate) 899 if (pass && dev->subordinate) {
800 pci_bus_size_bridges(dev->subordinate); 900 pci_bus_size_bridges(dev->subordinate);
901 func = get_func(slot, dev);
902 if (func) {
903 acpiphp_bus_add(func);
904 /* side effect of get_func */
905 pci_dev_put(dev);
906 }
907 }
801 } 908 }
802 } 909 }
803 } 910 }