diff options
Diffstat (limited to 'drivers/pci')
40 files changed, 2186 insertions, 683 deletions
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index b1ecefa2a23d..7858a117e80b 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig | |||
| @@ -21,17 +21,6 @@ config PCI_MSI | |||
| 21 | 21 | ||
| 22 | If you don't know what to do here, say N. | 22 | If you don't know what to do here, say N. |
| 23 | 23 | ||
| 24 | config PCI_LEGACY | ||
| 25 | bool "Enable deprecated pci_find_* API" | ||
| 26 | depends on PCI | ||
| 27 | default y | ||
| 28 | help | ||
| 29 | Say Y here if you want to include support for the deprecated | ||
| 30 | pci_find_device() API. Most drivers have been converted over | ||
| 31 | to using the proper hotplug APIs, so this option serves to | ||
| 32 | include/exclude only a few drivers that are still using this | ||
| 33 | API. | ||
| 34 | |||
| 35 | config PCI_DEBUG | 24 | config PCI_DEBUG |
| 36 | bool "PCI Debugging" | 25 | bool "PCI Debugging" |
| 37 | depends on PCI && DEBUG_KERNEL | 26 | depends on PCI && DEBUG_KERNEL |
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 4df48d58eaa6..8674c1ebe979 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile | |||
| @@ -2,14 +2,13 @@ | |||
| 2 | # Makefile for the PCI bus specific drivers. | 2 | # Makefile for the PCI bus specific drivers. |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \ | 5 | obj-y += access.o bus.o probe.o remove.o pci.o \ |
| 6 | pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ | 6 | pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ |
| 7 | irq.o | 7 | irq.o |
| 8 | obj-$(CONFIG_PROC_FS) += proc.o | 8 | obj-$(CONFIG_PROC_FS) += proc.o |
| 9 | obj-$(CONFIG_SYSFS) += slot.o | 9 | obj-$(CONFIG_SYSFS) += slot.o |
| 10 | 10 | ||
| 11 | obj-$(CONFIG_PCI_LEGACY) += legacy.o | 11 | obj-$(CONFIG_PCI_QUIRKS) += quirks.o |
| 12 | CFLAGS_legacy.o += -Wno-deprecated-declarations | ||
| 13 | 12 | ||
| 14 | # Build PCI Express stuff if needed | 13 | # Build PCI Express stuff if needed |
| 15 | obj-$(CONFIG_PCIEPORTBUS) += pcie/ | 14 | obj-$(CONFIG_PCIEPORTBUS) += pcie/ |
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index cef28a79103f..712250f5874a 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c | |||
| @@ -17,6 +17,52 @@ | |||
| 17 | 17 | ||
| 18 | #include "pci.h" | 18 | #include "pci.h" |
| 19 | 19 | ||
| 20 | void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, | ||
| 21 | unsigned int flags) | ||
| 22 | { | ||
| 23 | struct pci_bus_resource *bus_res; | ||
| 24 | |||
| 25 | bus_res = kzalloc(sizeof(struct pci_bus_resource), GFP_KERNEL); | ||
| 26 | if (!bus_res) { | ||
| 27 | dev_err(&bus->dev, "can't add %pR resource\n", res); | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | |||
| 31 | bus_res->res = res; | ||
| 32 | bus_res->flags = flags; | ||
| 33 | list_add_tail(&bus_res->list, &bus->resources); | ||
| 34 | } | ||
| 35 | |||
| 36 | struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n) | ||
| 37 | { | ||
| 38 | struct pci_bus_resource *bus_res; | ||
| 39 | |||
| 40 | if (n < PCI_BRIDGE_RESOURCE_NUM) | ||
| 41 | return bus->resource[n]; | ||
| 42 | |||
| 43 | n -= PCI_BRIDGE_RESOURCE_NUM; | ||
| 44 | list_for_each_entry(bus_res, &bus->resources, list) { | ||
| 45 | if (n-- == 0) | ||
| 46 | return bus_res->res; | ||
| 47 | } | ||
| 48 | return NULL; | ||
| 49 | } | ||
| 50 | EXPORT_SYMBOL_GPL(pci_bus_resource_n); | ||
| 51 | |||
| 52 | void pci_bus_remove_resources(struct pci_bus *bus) | ||
| 53 | { | ||
| 54 | struct pci_bus_resource *bus_res, *tmp; | ||
| 55 | int i; | ||
| 56 | |||
| 57 | for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) | ||
| 58 | bus->resource[i] = 0; | ||
| 59 | |||
| 60 | list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) { | ||
| 61 | list_del(&bus_res->list); | ||
| 62 | kfree(bus_res); | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 20 | /** | 66 | /** |
| 21 | * pci_bus_alloc_resource - allocate a resource from a parent bus | 67 | * pci_bus_alloc_resource - allocate a resource from a parent bus |
| 22 | * @bus: PCI bus | 68 | * @bus: PCI bus |
| @@ -36,11 +82,14 @@ int | |||
| 36 | pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, | 82 | pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, |
| 37 | resource_size_t size, resource_size_t align, | 83 | resource_size_t size, resource_size_t align, |
| 38 | resource_size_t min, unsigned int type_mask, | 84 | resource_size_t min, unsigned int type_mask, |
| 39 | void (*alignf)(void *, struct resource *, resource_size_t, | 85 | resource_size_t (*alignf)(void *, |
| 40 | resource_size_t), | 86 | const struct resource *, |
| 87 | resource_size_t, | ||
| 88 | resource_size_t), | ||
| 41 | void *alignf_data) | 89 | void *alignf_data) |
| 42 | { | 90 | { |
| 43 | int i, ret = -ENOMEM; | 91 | int i, ret = -ENOMEM; |
| 92 | struct resource *r; | ||
| 44 | resource_size_t max = -1; | 93 | resource_size_t max = -1; |
| 45 | 94 | ||
| 46 | type_mask |= IORESOURCE_IO | IORESOURCE_MEM; | 95 | type_mask |= IORESOURCE_IO | IORESOURCE_MEM; |
| @@ -49,8 +98,7 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, | |||
| 49 | if (!(res->flags & IORESOURCE_MEM_64)) | 98 | if (!(res->flags & IORESOURCE_MEM_64)) |
| 50 | max = PCIBIOS_MAX_MEM_32; | 99 | max = PCIBIOS_MAX_MEM_32; |
| 51 | 100 | ||
| 52 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | 101 | pci_bus_for_each_resource(bus, r, i) { |
| 53 | struct resource *r = bus->resource[i]; | ||
| 54 | if (!r) | 102 | if (!r) |
| 55 | continue; | 103 | continue; |
| 56 | 104 | ||
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index 4dd7114964ac..efa9f2de51c1 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c | |||
| @@ -332,8 +332,6 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) | |||
| 332 | slot->hotplug_slot->info->attention_status = 0; | 332 | slot->hotplug_slot->info->attention_status = 0; |
| 333 | slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); | 333 | slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); |
| 334 | slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); | 334 | slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); |
| 335 | slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; | ||
| 336 | slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; | ||
| 337 | 335 | ||
| 338 | acpiphp_slot->slot = slot; | 336 | acpiphp_slot->slot = slot; |
| 339 | snprintf(name, SLOT_NAME_SIZE, "%llu", slot->acpi_slot->sun); | 337 | snprintf(name, SLOT_NAME_SIZE, "%llu", slot->acpi_slot->sun); |
diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c index 148fb463b81c..fb3f84661bdc 100644 --- a/drivers/pci/hotplug/cpcihp_generic.c +++ b/drivers/pci/hotplug/cpcihp_generic.c | |||
| @@ -162,6 +162,7 @@ static int __init cpcihp_generic_init(void) | |||
| 162 | dev = pci_get_slot(bus, PCI_DEVFN(bridge_slot, 0)); | 162 | dev = pci_get_slot(bus, PCI_DEVFN(bridge_slot, 0)); |
| 163 | if(!dev || dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { | 163 | if(!dev || dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { |
| 164 | err("Invalid bridge device %s", bridge); | 164 | err("Invalid bridge device %s", bridge); |
| 165 | pci_dev_put(dev); | ||
| 165 | return -EINVAL; | 166 | return -EINVAL; |
| 166 | } | 167 | } |
| 167 | bus = dev->subordinate; | 168 | bus = dev->subordinate; |
diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index 9c6a9fd26812..d8ffc7366801 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h | |||
| @@ -310,8 +310,6 @@ struct controller { | |||
| 310 | u8 first_slot; | 310 | u8 first_slot; |
| 311 | u8 add_support; | 311 | u8 add_support; |
| 312 | u8 push_flag; | 312 | u8 push_flag; |
| 313 | enum pci_bus_speed speed; | ||
| 314 | enum pci_bus_speed speed_capability; | ||
| 315 | u8 push_button; /* 0 = no pushbutton, 1 = pushbutton present */ | 313 | u8 push_button; /* 0 = no pushbutton, 1 = pushbutton present */ |
| 316 | u8 slot_switch_type; /* 0 = no switch, 1 = switch present */ | 314 | u8 slot_switch_type; /* 0 = no switch, 1 = switch present */ |
| 317 | u8 defeature_PHP; /* 0 = PHP not supported, 1 = PHP supported */ | 315 | u8 defeature_PHP; /* 0 = PHP not supported, 1 = PHP supported */ |
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 075b4f4b6e0d..f184d1d2ecbe 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c | |||
| @@ -583,30 +583,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) | |||
| 583 | return 0; | 583 | return 0; |
| 584 | } | 584 | } |
| 585 | 585 | ||
| 586 | static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | ||
| 587 | { | ||
| 588 | struct slot *slot = hotplug_slot->private; | ||
| 589 | struct controller *ctrl = slot->ctrl; | ||
| 590 | |||
| 591 | dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); | ||
| 592 | |||
| 593 | *value = ctrl->speed_capability; | ||
| 594 | |||
| 595 | return 0; | ||
| 596 | } | ||
| 597 | |||
| 598 | static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | ||
| 599 | { | ||
| 600 | struct slot *slot = hotplug_slot->private; | ||
| 601 | struct controller *ctrl = slot->ctrl; | ||
| 602 | |||
| 603 | dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); | ||
| 604 | |||
| 605 | *value = ctrl->speed; | ||
| 606 | |||
| 607 | return 0; | ||
| 608 | } | ||
| 609 | |||
| 610 | static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { | 586 | static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { |
| 611 | .set_attention_status = set_attention_status, | 587 | .set_attention_status = set_attention_status, |
| 612 | .enable_slot = process_SI, | 588 | .enable_slot = process_SI, |
| @@ -616,8 +592,6 @@ static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { | |||
| 616 | .get_attention_status = get_attention_status, | 592 | .get_attention_status = get_attention_status, |
| 617 | .get_latch_status = get_latch_status, | 593 | .get_latch_status = get_latch_status, |
| 618 | .get_adapter_status = get_adapter_status, | 594 | .get_adapter_status = get_adapter_status, |
| 619 | .get_max_bus_speed = get_max_bus_speed, | ||
| 620 | .get_cur_bus_speed = get_cur_bus_speed, | ||
| 621 | }; | 595 | }; |
| 622 | 596 | ||
| 623 | #define SLOT_NAME_SIZE 10 | 597 | #define SLOT_NAME_SIZE 10 |
| @@ -629,6 +603,7 @@ static int ctrl_slot_setup(struct controller *ctrl, | |||
| 629 | struct slot *slot; | 603 | struct slot *slot; |
| 630 | struct hotplug_slot *hotplug_slot; | 604 | struct hotplug_slot *hotplug_slot; |
| 631 | struct hotplug_slot_info *hotplug_slot_info; | 605 | struct hotplug_slot_info *hotplug_slot_info; |
| 606 | struct pci_bus *bus = ctrl->pci_bus; | ||
| 632 | u8 number_of_slots; | 607 | u8 number_of_slots; |
| 633 | u8 slot_device; | 608 | u8 slot_device; |
| 634 | u8 slot_number; | 609 | u8 slot_number; |
| @@ -694,7 +669,7 @@ static int ctrl_slot_setup(struct controller *ctrl, | |||
| 694 | slot->capabilities |= PCISLOT_64_BIT_SUPPORTED; | 669 | slot->capabilities |= PCISLOT_64_BIT_SUPPORTED; |
| 695 | if (is_slot66mhz(slot)) | 670 | if (is_slot66mhz(slot)) |
| 696 | slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED; | 671 | slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED; |
| 697 | if (ctrl->speed == PCI_SPEED_66MHz) | 672 | if (bus->cur_bus_speed == PCI_SPEED_66MHz) |
| 698 | slot->capabilities |= PCISLOT_66_MHZ_OPERATION; | 673 | slot->capabilities |= PCISLOT_66_MHZ_OPERATION; |
| 699 | 674 | ||
| 700 | ctrl_slot = | 675 | ctrl_slot = |
| @@ -844,6 +819,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 844 | u32 rc; | 819 | u32 rc; |
| 845 | struct controller *ctrl; | 820 | struct controller *ctrl; |
| 846 | struct pci_func *func; | 821 | struct pci_func *func; |
| 822 | struct pci_bus *bus; | ||
| 847 | int err; | 823 | int err; |
| 848 | 824 | ||
| 849 | err = pci_enable_device(pdev); | 825 | err = pci_enable_device(pdev); |
| @@ -852,6 +828,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 852 | pci_name(pdev), err); | 828 | pci_name(pdev), err); |
| 853 | return err; | 829 | return err; |
| 854 | } | 830 | } |
| 831 | bus = pdev->subordinate; | ||
| 855 | 832 | ||
| 856 | /* Need to read VID early b/c it's used to differentiate CPQ and INTC | 833 | /* Need to read VID early b/c it's used to differentiate CPQ and INTC |
| 857 | * discovery | 834 | * discovery |
| @@ -929,22 +906,22 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 929 | pci_read_config_byte(pdev, 0x41, &bus_cap); | 906 | pci_read_config_byte(pdev, 0x41, &bus_cap); |
| 930 | if (bus_cap & 0x80) { | 907 | if (bus_cap & 0x80) { |
| 931 | dbg("bus max supports 133MHz PCI-X\n"); | 908 | dbg("bus max supports 133MHz PCI-X\n"); |
| 932 | ctrl->speed_capability = PCI_SPEED_133MHz_PCIX; | 909 | bus->max_bus_speed = PCI_SPEED_133MHz_PCIX; |
| 933 | break; | 910 | break; |
| 934 | } | 911 | } |
| 935 | if (bus_cap & 0x40) { | 912 | if (bus_cap & 0x40) { |
| 936 | dbg("bus max supports 100MHz PCI-X\n"); | 913 | dbg("bus max supports 100MHz PCI-X\n"); |
| 937 | ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; | 914 | bus->max_bus_speed = PCI_SPEED_100MHz_PCIX; |
| 938 | break; | 915 | break; |
| 939 | } | 916 | } |
| 940 | if (bus_cap & 20) { | 917 | if (bus_cap & 20) { |
| 941 | dbg("bus max supports 66MHz PCI-X\n"); | 918 | dbg("bus max supports 66MHz PCI-X\n"); |
| 942 | ctrl->speed_capability = PCI_SPEED_66MHz_PCIX; | 919 | bus->max_bus_speed = PCI_SPEED_66MHz_PCIX; |
| 943 | break; | 920 | break; |
| 944 | } | 921 | } |
| 945 | if (bus_cap & 10) { | 922 | if (bus_cap & 10) { |
| 946 | dbg("bus max supports 66MHz PCI\n"); | 923 | dbg("bus max supports 66MHz PCI\n"); |
| 947 | ctrl->speed_capability = PCI_SPEED_66MHz; | 924 | bus->max_bus_speed = PCI_SPEED_66MHz; |
| 948 | break; | 925 | break; |
| 949 | } | 926 | } |
| 950 | 927 | ||
| @@ -955,7 +932,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 955 | case PCI_SUB_HPC_ID: | 932 | case PCI_SUB_HPC_ID: |
| 956 | /* Original 6500/7000 implementation */ | 933 | /* Original 6500/7000 implementation */ |
| 957 | ctrl->slot_switch_type = 1; | 934 | ctrl->slot_switch_type = 1; |
| 958 | ctrl->speed_capability = PCI_SPEED_33MHz; | 935 | bus->max_bus_speed = PCI_SPEED_33MHz; |
| 959 | ctrl->push_button = 0; | 936 | ctrl->push_button = 0; |
| 960 | ctrl->pci_config_space = 1; | 937 | ctrl->pci_config_space = 1; |
| 961 | ctrl->defeature_PHP = 1; | 938 | ctrl->defeature_PHP = 1; |
| @@ -966,7 +943,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 966 | /* First Pushbutton implementation */ | 943 | /* First Pushbutton implementation */ |
| 967 | ctrl->push_flag = 1; | 944 | ctrl->push_flag = 1; |
| 968 | ctrl->slot_switch_type = 1; | 945 | ctrl->slot_switch_type = 1; |
| 969 | ctrl->speed_capability = PCI_SPEED_33MHz; | 946 | bus->max_bus_speed = PCI_SPEED_33MHz; |
| 970 | ctrl->push_button = 1; | 947 | ctrl->push_button = 1; |
| 971 | ctrl->pci_config_space = 1; | 948 | ctrl->pci_config_space = 1; |
| 972 | ctrl->defeature_PHP = 1; | 949 | ctrl->defeature_PHP = 1; |
| @@ -976,7 +953,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 976 | case PCI_SUB_HPC_ID_INTC: | 953 | case PCI_SUB_HPC_ID_INTC: |
| 977 | /* Third party (6500/7000) */ | 954 | /* Third party (6500/7000) */ |
| 978 | ctrl->slot_switch_type = 1; | 955 | ctrl->slot_switch_type = 1; |
| 979 | ctrl->speed_capability = PCI_SPEED_33MHz; | 956 | bus->max_bus_speed = PCI_SPEED_33MHz; |
| 980 | ctrl->push_button = 0; | 957 | ctrl->push_button = 0; |
| 981 | ctrl->pci_config_space = 1; | 958 | ctrl->pci_config_space = 1; |
| 982 | ctrl->defeature_PHP = 1; | 959 | ctrl->defeature_PHP = 1; |
| @@ -987,7 +964,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 987 | /* First 66 Mhz implementation */ | 964 | /* First 66 Mhz implementation */ |
| 988 | ctrl->push_flag = 1; | 965 | ctrl->push_flag = 1; |
| 989 | ctrl->slot_switch_type = 1; | 966 | ctrl->slot_switch_type = 1; |
| 990 | ctrl->speed_capability = PCI_SPEED_66MHz; | 967 | bus->max_bus_speed = PCI_SPEED_66MHz; |
| 991 | ctrl->push_button = 1; | 968 | ctrl->push_button = 1; |
| 992 | ctrl->pci_config_space = 1; | 969 | ctrl->pci_config_space = 1; |
| 993 | ctrl->defeature_PHP = 1; | 970 | ctrl->defeature_PHP = 1; |
| @@ -998,7 +975,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 998 | /* First PCI-X implementation, 100MHz */ | 975 | /* First PCI-X implementation, 100MHz */ |
| 999 | ctrl->push_flag = 1; | 976 | ctrl->push_flag = 1; |
| 1000 | ctrl->slot_switch_type = 1; | 977 | ctrl->slot_switch_type = 1; |
| 1001 | ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; | 978 | bus->max_bus_speed = PCI_SPEED_100MHz_PCIX; |
| 1002 | ctrl->push_button = 1; | 979 | ctrl->push_button = 1; |
| 1003 | ctrl->pci_config_space = 1; | 980 | ctrl->pci_config_space = 1; |
| 1004 | ctrl->defeature_PHP = 1; | 981 | ctrl->defeature_PHP = 1; |
| @@ -1015,9 +992,9 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 1015 | case PCI_VENDOR_ID_INTEL: | 992 | case PCI_VENDOR_ID_INTEL: |
| 1016 | /* Check for speed capability (0=33, 1=66) */ | 993 | /* Check for speed capability (0=33, 1=66) */ |
| 1017 | if (subsystem_deviceid & 0x0001) | 994 | if (subsystem_deviceid & 0x0001) |
| 1018 | ctrl->speed_capability = PCI_SPEED_66MHz; | 995 | bus->max_bus_speed = PCI_SPEED_66MHz; |
| 1019 | else | 996 | else |
| 1020 | ctrl->speed_capability = PCI_SPEED_33MHz; | 997 | bus->max_bus_speed = PCI_SPEED_33MHz; |
| 1021 | 998 | ||
| 1022 | /* Check for push button */ | 999 | /* Check for push button */ |
| 1023 | if (subsystem_deviceid & 0x0002) | 1000 | if (subsystem_deviceid & 0x0002) |
| @@ -1079,7 +1056,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 1079 | pdev->bus->number); | 1056 | pdev->bus->number); |
| 1080 | 1057 | ||
| 1081 | dbg("Hotplug controller capabilities:\n"); | 1058 | dbg("Hotplug controller capabilities:\n"); |
| 1082 | dbg(" speed_capability %d\n", ctrl->speed_capability); | 1059 | dbg(" speed_capability %d\n", bus->max_bus_speed); |
| 1083 | dbg(" slot_switch_type %s\n", ctrl->slot_switch_type ? | 1060 | dbg(" slot_switch_type %s\n", ctrl->slot_switch_type ? |
| 1084 | "switch present" : "no switch"); | 1061 | "switch present" : "no switch"); |
| 1085 | dbg(" defeature_PHP %s\n", ctrl->defeature_PHP ? | 1062 | dbg(" defeature_PHP %s\n", ctrl->defeature_PHP ? |
| @@ -1142,7 +1119,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 1142 | } | 1119 | } |
| 1143 | 1120 | ||
| 1144 | /* Check for 66Mhz operation */ | 1121 | /* Check for 66Mhz operation */ |
| 1145 | ctrl->speed = get_controller_speed(ctrl); | 1122 | bus->cur_bus_speed = get_controller_speed(ctrl); |
| 1146 | 1123 | ||
| 1147 | 1124 | ||
| 1148 | /******************************************************** | 1125 | /******************************************************** |
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 0ff689afa757..e43908d9b5df 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c | |||
| @@ -1130,12 +1130,13 @@ static int is_bridge(struct pci_func * func) | |||
| 1130 | static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot) | 1130 | static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot) |
| 1131 | { | 1131 | { |
| 1132 | struct slot *slot; | 1132 | struct slot *slot; |
| 1133 | struct pci_bus *bus = ctrl->pci_bus; | ||
| 1133 | u8 reg; | 1134 | u8 reg; |
| 1134 | u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER); | 1135 | u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER); |
| 1135 | u16 reg16; | 1136 | u16 reg16; |
| 1136 | u32 leds = readl(ctrl->hpc_reg + LED_CONTROL); | 1137 | u32 leds = readl(ctrl->hpc_reg + LED_CONTROL); |
| 1137 | 1138 | ||
| 1138 | if (ctrl->speed == adapter_speed) | 1139 | if (bus->cur_bus_speed == adapter_speed) |
| 1139 | return 0; | 1140 | return 0; |
| 1140 | 1141 | ||
| 1141 | /* We don't allow freq/mode changes if we find another adapter running | 1142 | /* We don't allow freq/mode changes if we find another adapter running |
| @@ -1152,7 +1153,7 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ | |||
| 1152 | * lower speed/mode, we allow the new adapter to function at | 1153 | * lower speed/mode, we allow the new adapter to function at |
| 1153 | * this rate if supported | 1154 | * this rate if supported |
| 1154 | */ | 1155 | */ |
| 1155 | if (ctrl->speed < adapter_speed) | 1156 | if (bus->cur_bus_speed < adapter_speed) |
| 1156 | return 0; | 1157 | return 0; |
| 1157 | 1158 | ||
| 1158 | return 1; | 1159 | return 1; |
| @@ -1161,20 +1162,20 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ | |||
| 1161 | /* If the controller doesn't support freq/mode changes and the | 1162 | /* If the controller doesn't support freq/mode changes and the |
| 1162 | * controller is running at a higher mode, we bail | 1163 | * controller is running at a higher mode, we bail |
| 1163 | */ | 1164 | */ |
| 1164 | if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability)) | 1165 | if ((bus->cur_bus_speed > adapter_speed) && (!ctrl->pcix_speed_capability)) |
| 1165 | return 1; | 1166 | return 1; |
| 1166 | 1167 | ||
| 1167 | /* But we allow the adapter to run at a lower rate if possible */ | 1168 | /* But we allow the adapter to run at a lower rate if possible */ |
| 1168 | if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability)) | 1169 | if ((bus->cur_bus_speed < adapter_speed) && (!ctrl->pcix_speed_capability)) |
| 1169 | return 0; | 1170 | return 0; |
| 1170 | 1171 | ||
| 1171 | /* We try to set the max speed supported by both the adapter and | 1172 | /* We try to set the max speed supported by both the adapter and |
| 1172 | * controller | 1173 | * controller |
| 1173 | */ | 1174 | */ |
| 1174 | if (ctrl->speed_capability < adapter_speed) { | 1175 | if (bus->max_bus_speed < adapter_speed) { |
| 1175 | if (ctrl->speed == ctrl->speed_capability) | 1176 | if (bus->cur_bus_speed == bus->max_bus_speed) |
| 1176 | return 0; | 1177 | return 0; |
| 1177 | adapter_speed = ctrl->speed_capability; | 1178 | adapter_speed = bus->max_bus_speed; |
| 1178 | } | 1179 | } |
| 1179 | 1180 | ||
| 1180 | writel(0x0L, ctrl->hpc_reg + LED_CONTROL); | 1181 | writel(0x0L, ctrl->hpc_reg + LED_CONTROL); |
| @@ -1229,8 +1230,8 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ | |||
| 1229 | pci_write_config_byte(ctrl->pci_dev, 0x43, reg); | 1230 | pci_write_config_byte(ctrl->pci_dev, 0x43, reg); |
| 1230 | 1231 | ||
| 1231 | /* Only if mode change...*/ | 1232 | /* Only if mode change...*/ |
| 1232 | if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) || | 1233 | if (((bus->cur_bus_speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) || |
| 1233 | ((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) | 1234 | ((bus->cur_bus_speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) |
| 1234 | set_SOGO(ctrl); | 1235 | set_SOGO(ctrl); |
| 1235 | 1236 | ||
| 1236 | wait_for_ctrl_irq(ctrl); | 1237 | wait_for_ctrl_irq(ctrl); |
| @@ -1243,7 +1244,7 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ | |||
| 1243 | set_SOGO(ctrl); | 1244 | set_SOGO(ctrl); |
| 1244 | wait_for_ctrl_irq(ctrl); | 1245 | wait_for_ctrl_irq(ctrl); |
| 1245 | 1246 | ||
| 1246 | ctrl->speed = adapter_speed; | 1247 | bus->cur_bus_speed = adapter_speed; |
| 1247 | slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 1248 | slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
| 1248 | 1249 | ||
| 1249 | info("Successfully changed frequency/mode for adapter in slot %d\n", | 1250 | info("Successfully changed frequency/mode for adapter in slot %d\n", |
| @@ -1269,6 +1270,7 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ | |||
| 1269 | */ | 1270 | */ |
| 1270 | static u32 board_replaced(struct pci_func *func, struct controller *ctrl) | 1271 | static u32 board_replaced(struct pci_func *func, struct controller *ctrl) |
| 1271 | { | 1272 | { |
| 1273 | struct pci_bus *bus = ctrl->pci_bus; | ||
| 1272 | u8 hp_slot; | 1274 | u8 hp_slot; |
| 1273 | u8 temp_byte; | 1275 | u8 temp_byte; |
| 1274 | u8 adapter_speed; | 1276 | u8 adapter_speed; |
| @@ -1309,7 +1311,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) | |||
| 1309 | wait_for_ctrl_irq (ctrl); | 1311 | wait_for_ctrl_irq (ctrl); |
| 1310 | 1312 | ||
| 1311 | adapter_speed = get_adapter_speed(ctrl, hp_slot); | 1313 | adapter_speed = get_adapter_speed(ctrl, hp_slot); |
| 1312 | if (ctrl->speed != adapter_speed) | 1314 | if (bus->cur_bus_speed != adapter_speed) |
| 1313 | if (set_controller_speed(ctrl, adapter_speed, hp_slot)) | 1315 | if (set_controller_speed(ctrl, adapter_speed, hp_slot)) |
| 1314 | rc = WRONG_BUS_FREQUENCY; | 1316 | rc = WRONG_BUS_FREQUENCY; |
| 1315 | 1317 | ||
| @@ -1426,6 +1428,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) | |||
| 1426 | u32 temp_register = 0xFFFFFFFF; | 1428 | u32 temp_register = 0xFFFFFFFF; |
| 1427 | u32 rc = 0; | 1429 | u32 rc = 0; |
| 1428 | struct pci_func *new_slot = NULL; | 1430 | struct pci_func *new_slot = NULL; |
| 1431 | struct pci_bus *bus = ctrl->pci_bus; | ||
| 1429 | struct slot *p_slot; | 1432 | struct slot *p_slot; |
| 1430 | struct resource_lists res_lists; | 1433 | struct resource_lists res_lists; |
| 1431 | 1434 | ||
| @@ -1456,7 +1459,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) | |||
| 1456 | wait_for_ctrl_irq (ctrl); | 1459 | wait_for_ctrl_irq (ctrl); |
| 1457 | 1460 | ||
| 1458 | adapter_speed = get_adapter_speed(ctrl, hp_slot); | 1461 | adapter_speed = get_adapter_speed(ctrl, hp_slot); |
| 1459 | if (ctrl->speed != adapter_speed) | 1462 | if (bus->cur_bus_speed != adapter_speed) |
| 1460 | if (set_controller_speed(ctrl, adapter_speed, hp_slot)) | 1463 | if (set_controller_speed(ctrl, adapter_speed, hp_slot)) |
| 1461 | rc = WRONG_BUS_FREQUENCY; | 1464 | rc = WRONG_BUS_FREQUENCY; |
| 1462 | 1465 | ||
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index 7485ffda950c..d934dd4fa873 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c | |||
| @@ -395,89 +395,40 @@ static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 * value) | |||
| 395 | return rc; | 395 | return rc; |
| 396 | } | 396 | } |
| 397 | 397 | ||
| 398 | static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | 398 | static int get_max_bus_speed(struct slot *slot) |
| 399 | { | 399 | { |
| 400 | int rc = -ENODEV; | 400 | int rc; |
| 401 | struct slot *pslot; | ||
| 402 | u8 mode = 0; | 401 | u8 mode = 0; |
| 402 | enum pci_bus_speed speed; | ||
| 403 | struct pci_bus *bus = slot->hotplug_slot->pci_slot->bus; | ||
| 403 | 404 | ||
| 404 | debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __func__, | 405 | debug("%s - Entry slot[%p]\n", __func__, slot); |
| 405 | hotplug_slot, value); | ||
| 406 | 406 | ||
| 407 | ibmphp_lock_operations(); | 407 | ibmphp_lock_operations(); |
| 408 | 408 | mode = slot->supported_bus_mode; | |
| 409 | if (hotplug_slot) { | 409 | speed = slot->supported_speed; |
| 410 | pslot = hotplug_slot->private; | ||
| 411 | if (pslot) { | ||
| 412 | rc = 0; | ||
| 413 | mode = pslot->supported_bus_mode; | ||
| 414 | *value = pslot->supported_speed; | ||
| 415 | switch (*value) { | ||
| 416 | case BUS_SPEED_33: | ||
| 417 | break; | ||
| 418 | case BUS_SPEED_66: | ||
| 419 | if (mode == BUS_MODE_PCIX) | ||
| 420 | *value += 0x01; | ||
| 421 | break; | ||
| 422 | case BUS_SPEED_100: | ||
| 423 | case BUS_SPEED_133: | ||
| 424 | *value = pslot->supported_speed + 0x01; | ||
| 425 | break; | ||
| 426 | default: | ||
| 427 | /* Note (will need to change): there would be soon 256, 512 also */ | ||
| 428 | rc = -ENODEV; | ||
| 429 | } | ||
| 430 | } | ||
| 431 | } | ||
| 432 | |||
| 433 | ibmphp_unlock_operations(); | 410 | ibmphp_unlock_operations(); |
| 434 | debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value); | ||
| 435 | return rc; | ||
| 436 | } | ||
| 437 | 411 | ||
| 438 | static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | 412 | switch (speed) { |
| 439 | { | 413 | case BUS_SPEED_33: |
| 440 | int rc = -ENODEV; | 414 | break; |
| 441 | struct slot *pslot; | 415 | case BUS_SPEED_66: |
| 442 | u8 mode = 0; | 416 | if (mode == BUS_MODE_PCIX) |
| 443 | 417 | speed += 0x01; | |
| 444 | debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __func__, | 418 | break; |
| 445 | hotplug_slot, value); | 419 | case BUS_SPEED_100: |
| 446 | 420 | case BUS_SPEED_133: | |
| 447 | ibmphp_lock_operations(); | 421 | speed += 0x01; |
| 448 | 422 | break; | |
| 449 | if (hotplug_slot) { | 423 | default: |
| 450 | pslot = hotplug_slot->private; | 424 | /* Note (will need to change): there would be soon 256, 512 also */ |
| 451 | if (pslot) { | 425 | rc = -ENODEV; |
| 452 | rc = get_cur_bus_info(&pslot); | ||
| 453 | if (!rc) { | ||
| 454 | mode = pslot->bus_on->current_bus_mode; | ||
| 455 | *value = pslot->bus_on->current_speed; | ||
| 456 | switch (*value) { | ||
| 457 | case BUS_SPEED_33: | ||
| 458 | break; | ||
| 459 | case BUS_SPEED_66: | ||
| 460 | if (mode == BUS_MODE_PCIX) | ||
| 461 | *value += 0x01; | ||
| 462 | else if (mode == BUS_MODE_PCI) | ||
| 463 | ; | ||
| 464 | else | ||
| 465 | *value = PCI_SPEED_UNKNOWN; | ||
| 466 | break; | ||
| 467 | case BUS_SPEED_100: | ||
| 468 | case BUS_SPEED_133: | ||
| 469 | *value += 0x01; | ||
| 470 | break; | ||
| 471 | default: | ||
| 472 | /* Note of change: there would also be 256, 512 soon */ | ||
| 473 | rc = -ENODEV; | ||
| 474 | } | ||
| 475 | } | ||
| 476 | } | ||
| 477 | } | 426 | } |
| 478 | 427 | ||
| 479 | ibmphp_unlock_operations(); | 428 | if (!rc) |
| 480 | debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value); | 429 | bus->max_bus_speed = speed; |
| 430 | |||
| 431 | debug("%s - Exit rc[%d] speed[%x]\n", __func__, rc, speed); | ||
| 481 | return rc; | 432 | return rc; |
| 482 | } | 433 | } |
| 483 | 434 | ||
| @@ -572,6 +523,7 @@ static int __init init_ops(void) | |||
| 572 | if (slot_cur->bus_on->current_speed == 0xFF) | 523 | if (slot_cur->bus_on->current_speed == 0xFF) |
| 573 | if (get_cur_bus_info(&slot_cur)) | 524 | if (get_cur_bus_info(&slot_cur)) |
| 574 | return -1; | 525 | return -1; |
| 526 | get_max_bus_speed(slot_cur); | ||
| 575 | 527 | ||
| 576 | if (slot_cur->ctrl->options == 0xFF) | 528 | if (slot_cur->ctrl->options == 0xFF) |
| 577 | if (get_hpc_options(slot_cur, &slot_cur->ctrl->options)) | 529 | if (get_hpc_options(slot_cur, &slot_cur->ctrl->options)) |
| @@ -655,6 +607,7 @@ static int validate(struct slot *slot_cur, int opn) | |||
| 655 | int ibmphp_update_slot_info(struct slot *slot_cur) | 607 | int ibmphp_update_slot_info(struct slot *slot_cur) |
| 656 | { | 608 | { |
| 657 | struct hotplug_slot_info *info; | 609 | struct hotplug_slot_info *info; |
| 610 | struct pci_bus *bus = slot_cur->hotplug_slot->pci_slot->bus; | ||
| 658 | int rc; | 611 | int rc; |
| 659 | u8 bus_speed; | 612 | u8 bus_speed; |
| 660 | u8 mode; | 613 | u8 mode; |
| @@ -700,8 +653,7 @@ int ibmphp_update_slot_info(struct slot *slot_cur) | |||
| 700 | bus_speed = PCI_SPEED_UNKNOWN; | 653 | bus_speed = PCI_SPEED_UNKNOWN; |
| 701 | } | 654 | } |
| 702 | 655 | ||
| 703 | info->cur_bus_speed = bus_speed; | 656 | bus->cur_bus_speed = bus_speed; |
| 704 | info->max_bus_speed = slot_cur->hotplug_slot->info->max_bus_speed; | ||
| 705 | // To do: bus_names | 657 | // To do: bus_names |
| 706 | 658 | ||
| 707 | rc = pci_hp_change_slot_info(slot_cur->hotplug_slot, info); | 659 | rc = pci_hp_change_slot_info(slot_cur->hotplug_slot, info); |
| @@ -1326,8 +1278,6 @@ struct hotplug_slot_ops ibmphp_hotplug_slot_ops = { | |||
| 1326 | .get_attention_status = get_attention_status, | 1278 | .get_attention_status = get_attention_status, |
| 1327 | .get_latch_status = get_latch_status, | 1279 | .get_latch_status = get_latch_status, |
| 1328 | .get_adapter_status = get_adapter_present, | 1280 | .get_adapter_status = get_adapter_present, |
| 1329 | .get_max_bus_speed = get_max_bus_speed, | ||
| 1330 | .get_cur_bus_speed = get_cur_bus_speed, | ||
| 1331 | /* .get_max_adapter_speed = get_max_adapter_speed, | 1281 | /* .get_max_adapter_speed = get_max_adapter_speed, |
| 1332 | .get_bus_name_status = get_bus_name, | 1282 | .get_bus_name_status = get_bus_name, |
| 1333 | */ | 1283 | */ |
diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c index c1abac8ab5c3..5becbdee4027 100644 --- a/drivers/pci/hotplug/ibmphp_ebda.c +++ b/drivers/pci/hotplug/ibmphp_ebda.c | |||
| @@ -245,7 +245,7 @@ static void __init print_ebda_hpc (void) | |||
| 245 | 245 | ||
| 246 | int __init ibmphp_access_ebda (void) | 246 | int __init ibmphp_access_ebda (void) |
| 247 | { | 247 | { |
| 248 | u8 format, num_ctlrs, rio_complete, hs_complete; | 248 | u8 format, num_ctlrs, rio_complete, hs_complete, ebda_sz; |
| 249 | u16 ebda_seg, num_entries, next_offset, offset, blk_id, sub_addr, re, rc_id, re_id, base; | 249 | u16 ebda_seg, num_entries, next_offset, offset, blk_id, sub_addr, re, rc_id, re_id, base; |
| 250 | int rc = 0; | 250 | int rc = 0; |
| 251 | 251 | ||
| @@ -260,7 +260,16 @@ int __init ibmphp_access_ebda (void) | |||
| 260 | iounmap (io_mem); | 260 | iounmap (io_mem); |
| 261 | debug ("returned ebda segment: %x\n", ebda_seg); | 261 | debug ("returned ebda segment: %x\n", ebda_seg); |
| 262 | 262 | ||
| 263 | io_mem = ioremap(ebda_seg<<4, 1024); | 263 | io_mem = ioremap(ebda_seg<<4, 1); |
| 264 | if (!io_mem) | ||
| 265 | return -ENOMEM; | ||
| 266 | ebda_sz = readb(io_mem); | ||
| 267 | iounmap(io_mem); | ||
| 268 | debug("ebda size: %d(KiB)\n", ebda_sz); | ||
| 269 | if (ebda_sz == 0) | ||
| 270 | return -ENOMEM; | ||
| 271 | |||
| 272 | io_mem = ioremap(ebda_seg<<4, (ebda_sz * 1024)); | ||
| 264 | if (!io_mem ) | 273 | if (!io_mem ) |
| 265 | return -ENOMEM; | 274 | return -ENOMEM; |
| 266 | next_offset = 0x180; | 275 | next_offset = 0x180; |
diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c index c7084f0eca5a..1aaf3f32d3cd 100644 --- a/drivers/pci/hotplug/ibmphp_hpc.c +++ b/drivers/pci/hotplug/ibmphp_hpc.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
| 36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
| 37 | #include <linux/sched.h> | 37 | #include <linux/sched.h> |
| 38 | #include <linux/semaphore.h> | ||
| 38 | #include <linux/kthread.h> | 39 | #include <linux/kthread.h> |
| 39 | #include "ibmphp.h" | 40 | #include "ibmphp.h" |
| 40 | 41 | ||
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 38183a534b65..728b119f71ad 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c | |||
| @@ -64,32 +64,6 @@ static int debug; | |||
| 64 | static LIST_HEAD(pci_hotplug_slot_list); | 64 | static LIST_HEAD(pci_hotplug_slot_list); |
| 65 | static DEFINE_MUTEX(pci_hp_mutex); | 65 | static DEFINE_MUTEX(pci_hp_mutex); |
| 66 | 66 | ||
| 67 | /* these strings match up with the values in pci_bus_speed */ | ||
| 68 | static char *pci_bus_speed_strings[] = { | ||
| 69 | "33 MHz PCI", /* 0x00 */ | ||
| 70 | "66 MHz PCI", /* 0x01 */ | ||
| 71 | "66 MHz PCI-X", /* 0x02 */ | ||
| 72 | "100 MHz PCI-X", /* 0x03 */ | ||
| 73 | "133 MHz PCI-X", /* 0x04 */ | ||
| 74 | NULL, /* 0x05 */ | ||
| 75 | NULL, /* 0x06 */ | ||
| 76 | NULL, /* 0x07 */ | ||
| 77 | NULL, /* 0x08 */ | ||
| 78 | "66 MHz PCI-X 266", /* 0x09 */ | ||
| 79 | "100 MHz PCI-X 266", /* 0x0a */ | ||
| 80 | "133 MHz PCI-X 266", /* 0x0b */ | ||
| 81 | NULL, /* 0x0c */ | ||
| 82 | NULL, /* 0x0d */ | ||
| 83 | NULL, /* 0x0e */ | ||
| 84 | NULL, /* 0x0f */ | ||
| 85 | NULL, /* 0x10 */ | ||
| 86 | "66 MHz PCI-X 533", /* 0x11 */ | ||
| 87 | "100 MHz PCI-X 533", /* 0x12 */ | ||
| 88 | "133 MHz PCI-X 533", /* 0x13 */ | ||
| 89 | "2.5 GT/s PCIe", /* 0x14 */ | ||
| 90 | "5.0 GT/s PCIe", /* 0x15 */ | ||
| 91 | }; | ||
| 92 | |||
| 93 | #ifdef CONFIG_HOTPLUG_PCI_CPCI | 67 | #ifdef CONFIG_HOTPLUG_PCI_CPCI |
| 94 | extern int cpci_hotplug_init(int debug); | 68 | extern int cpci_hotplug_init(int debug); |
| 95 | extern void cpci_hotplug_exit(void); | 69 | extern void cpci_hotplug_exit(void); |
| @@ -118,8 +92,6 @@ GET_STATUS(power_status, u8) | |||
| 118 | GET_STATUS(attention_status, u8) | 92 | GET_STATUS(attention_status, u8) |
| 119 | GET_STATUS(latch_status, u8) | 93 | GET_STATUS(latch_status, u8) |
| 120 | GET_STATUS(adapter_status, u8) | 94 | GET_STATUS(adapter_status, u8) |
| 121 | GET_STATUS(max_bus_speed, enum pci_bus_speed) | ||
| 122 | GET_STATUS(cur_bus_speed, enum pci_bus_speed) | ||
| 123 | 95 | ||
| 124 | static ssize_t power_read_file(struct pci_slot *slot, char *buf) | 96 | static ssize_t power_read_file(struct pci_slot *slot, char *buf) |
| 125 | { | 97 | { |
| @@ -263,60 +235,6 @@ static struct pci_slot_attribute hotplug_slot_attr_presence = { | |||
| 263 | .show = presence_read_file, | 235 | .show = presence_read_file, |
| 264 | }; | 236 | }; |
| 265 | 237 | ||
| 266 | static char *unknown_speed = "Unknown bus speed"; | ||
| 267 | |||
| 268 | static ssize_t max_bus_speed_read_file(struct pci_slot *slot, char *buf) | ||
| 269 | { | ||
| 270 | char *speed_string; | ||
| 271 | int retval; | ||
| 272 | enum pci_bus_speed value; | ||
| 273 | |||
| 274 | retval = get_max_bus_speed(slot->hotplug, &value); | ||
| 275 | if (retval) | ||
| 276 | goto exit; | ||
| 277 | |||
| 278 | if (value == PCI_SPEED_UNKNOWN) | ||
| 279 | speed_string = unknown_speed; | ||
| 280 | else | ||
| 281 | speed_string = pci_bus_speed_strings[value]; | ||
| 282 | |||
| 283 | retval = sprintf (buf, "%s\n", speed_string); | ||
| 284 | |||
| 285 | exit: | ||
| 286 | return retval; | ||
| 287 | } | ||
| 288 | |||
| 289 | static struct pci_slot_attribute hotplug_slot_attr_max_bus_speed = { | ||
| 290 | .attr = {.name = "max_bus_speed", .mode = S_IFREG | S_IRUGO}, | ||
| 291 | .show = max_bus_speed_read_file, | ||
| 292 | }; | ||
| 293 | |||
| 294 | static ssize_t cur_bus_speed_read_file(struct pci_slot *slot, char *buf) | ||
| 295 | { | ||
| 296 | char *speed_string; | ||
| 297 | int retval; | ||
| 298 | enum pci_bus_speed value; | ||
| 299 | |||
| 300 | retval = get_cur_bus_speed(slot->hotplug, &value); | ||
| 301 | if (retval) | ||
| 302 | goto exit; | ||
| 303 | |||
| 304 | if (value == PCI_SPEED_UNKNOWN) | ||
| 305 | speed_string = unknown_speed; | ||
| 306 | else | ||
| 307 | speed_string = pci_bus_speed_strings[value]; | ||
| 308 | |||
| 309 | retval = sprintf (buf, "%s\n", speed_string); | ||
| 310 | |||
| 311 | exit: | ||
| 312 | return retval; | ||
| 313 | } | ||
| 314 | |||
| 315 | static struct pci_slot_attribute hotplug_slot_attr_cur_bus_speed = { | ||
| 316 | .attr = {.name = "cur_bus_speed", .mode = S_IFREG | S_IRUGO}, | ||
| 317 | .show = cur_bus_speed_read_file, | ||
| 318 | }; | ||
| 319 | |||
| 320 | static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf, | 238 | static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf, |
| 321 | size_t count) | 239 | size_t count) |
| 322 | { | 240 | { |
| @@ -391,26 +309,6 @@ static bool has_adapter_file(struct pci_slot *pci_slot) | |||
| 391 | return false; | 309 | return false; |
| 392 | } | 310 | } |
| 393 | 311 | ||
| 394 | static bool has_max_bus_speed_file(struct pci_slot *pci_slot) | ||
| 395 | { | ||
| 396 | struct hotplug_slot *slot = pci_slot->hotplug; | ||
| 397 | if ((!slot) || (!slot->ops)) | ||
| 398 | return false; | ||
| 399 | if (slot->ops->get_max_bus_speed) | ||
| 400 | return true; | ||
| 401 | return false; | ||
| 402 | } | ||
| 403 | |||
| 404 | static bool has_cur_bus_speed_file(struct pci_slot *pci_slot) | ||
| 405 | { | ||
| 406 | struct hotplug_slot *slot = pci_slot->hotplug; | ||
| 407 | if ((!slot) || (!slot->ops)) | ||
| 408 | return false; | ||
| 409 | if (slot->ops->get_cur_bus_speed) | ||
| 410 | return true; | ||
| 411 | return false; | ||
| 412 | } | ||
| 413 | |||
| 414 | static bool has_test_file(struct pci_slot *pci_slot) | 312 | static bool has_test_file(struct pci_slot *pci_slot) |
| 415 | { | 313 | { |
| 416 | struct hotplug_slot *slot = pci_slot->hotplug; | 314 | struct hotplug_slot *slot = pci_slot->hotplug; |
| @@ -456,20 +354,6 @@ static int fs_add_slot(struct pci_slot *slot) | |||
| 456 | goto exit_adapter; | 354 | goto exit_adapter; |
| 457 | } | 355 | } |
| 458 | 356 | ||
| 459 | if (has_max_bus_speed_file(slot)) { | ||
| 460 | retval = sysfs_create_file(&slot->kobj, | ||
| 461 | &hotplug_slot_attr_max_bus_speed.attr); | ||
| 462 | if (retval) | ||
| 463 | goto exit_max_speed; | ||
| 464 | } | ||
| 465 | |||
| 466 | if (has_cur_bus_speed_file(slot)) { | ||
| 467 | retval = sysfs_create_file(&slot->kobj, | ||
| 468 | &hotplug_slot_attr_cur_bus_speed.attr); | ||
| 469 | if (retval) | ||
| 470 | goto exit_cur_speed; | ||
| 471 | } | ||
| 472 | |||
| 473 | if (has_test_file(slot)) { | 357 | if (has_test_file(slot)) { |
| 474 | retval = sysfs_create_file(&slot->kobj, | 358 | retval = sysfs_create_file(&slot->kobj, |
| 475 | &hotplug_slot_attr_test.attr); | 359 | &hotplug_slot_attr_test.attr); |
| @@ -480,14 +364,6 @@ static int fs_add_slot(struct pci_slot *slot) | |||
| 480 | goto exit; | 364 | goto exit; |
| 481 | 365 | ||
| 482 | exit_test: | 366 | exit_test: |
| 483 | if (has_cur_bus_speed_file(slot)) | ||
| 484 | sysfs_remove_file(&slot->kobj, | ||
| 485 | &hotplug_slot_attr_cur_bus_speed.attr); | ||
| 486 | exit_cur_speed: | ||
| 487 | if (has_max_bus_speed_file(slot)) | ||
| 488 | sysfs_remove_file(&slot->kobj, | ||
| 489 | &hotplug_slot_attr_max_bus_speed.attr); | ||
| 490 | exit_max_speed: | ||
| 491 | if (has_adapter_file(slot)) | 367 | if (has_adapter_file(slot)) |
| 492 | sysfs_remove_file(&slot->kobj, | 368 | sysfs_remove_file(&slot->kobj, |
| 493 | &hotplug_slot_attr_presence.attr); | 369 | &hotplug_slot_attr_presence.attr); |
| @@ -523,14 +399,6 @@ static void fs_remove_slot(struct pci_slot *slot) | |||
| 523 | sysfs_remove_file(&slot->kobj, | 399 | sysfs_remove_file(&slot->kobj, |
| 524 | &hotplug_slot_attr_presence.attr); | 400 | &hotplug_slot_attr_presence.attr); |
| 525 | 401 | ||
| 526 | if (has_max_bus_speed_file(slot)) | ||
| 527 | sysfs_remove_file(&slot->kobj, | ||
| 528 | &hotplug_slot_attr_max_bus_speed.attr); | ||
| 529 | |||
| 530 | if (has_cur_bus_speed_file(slot)) | ||
| 531 | sysfs_remove_file(&slot->kobj, | ||
| 532 | &hotplug_slot_attr_cur_bus_speed.attr); | ||
| 533 | |||
| 534 | if (has_test_file(slot)) | 402 | if (has_test_file(slot)) |
| 535 | sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr); | 403 | sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr); |
| 536 | 404 | ||
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 5674b2075bdc..920f820edf87 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
| @@ -69,8 +69,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value); | |||
| 69 | static int get_attention_status (struct hotplug_slot *slot, u8 *value); | 69 | static int get_attention_status (struct hotplug_slot *slot, u8 *value); |
| 70 | static int get_latch_status (struct hotplug_slot *slot, u8 *value); | 70 | static int get_latch_status (struct hotplug_slot *slot, u8 *value); |
| 71 | static int get_adapter_status (struct hotplug_slot *slot, u8 *value); | 71 | static int get_adapter_status (struct hotplug_slot *slot, u8 *value); |
| 72 | static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
| 73 | static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
| 74 | 72 | ||
| 75 | /** | 73 | /** |
| 76 | * release_slot - free up the memory used by a slot | 74 | * release_slot - free up the memory used by a slot |
| @@ -113,8 +111,6 @@ static int init_slot(struct controller *ctrl) | |||
| 113 | ops->disable_slot = disable_slot; | 111 | ops->disable_slot = disable_slot; |
| 114 | ops->get_power_status = get_power_status; | 112 | ops->get_power_status = get_power_status; |
| 115 | ops->get_adapter_status = get_adapter_status; | 113 | ops->get_adapter_status = get_adapter_status; |
| 116 | ops->get_max_bus_speed = get_max_bus_speed; | ||
| 117 | ops->get_cur_bus_speed = get_cur_bus_speed; | ||
| 118 | if (MRL_SENS(ctrl)) | 114 | if (MRL_SENS(ctrl)) |
| 119 | ops->get_latch_status = get_latch_status; | 115 | ops->get_latch_status = get_latch_status; |
| 120 | if (ATTN_LED(ctrl)) { | 116 | if (ATTN_LED(ctrl)) { |
| @@ -227,27 +223,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) | |||
| 227 | return pciehp_get_adapter_status(slot, value); | 223 | return pciehp_get_adapter_status(slot, value); |
| 228 | } | 224 | } |
| 229 | 225 | ||
| 230 | static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, | ||
| 231 | enum pci_bus_speed *value) | ||
| 232 | { | ||
| 233 | struct slot *slot = hotplug_slot->private; | ||
| 234 | |||
| 235 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | ||
| 236 | __func__, slot_name(slot)); | ||
| 237 | |||
| 238 | return pciehp_get_max_link_speed(slot, value); | ||
| 239 | } | ||
| 240 | |||
| 241 | static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | ||
| 242 | { | ||
| 243 | struct slot *slot = hotplug_slot->private; | ||
| 244 | |||
| 245 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | ||
| 246 | __func__, slot_name(slot)); | ||
| 247 | |||
| 248 | return pciehp_get_cur_link_speed(slot, value); | ||
| 249 | } | ||
| 250 | |||
| 251 | static int pciehp_probe(struct pcie_device *dev) | 226 | static int pciehp_probe(struct pcie_device *dev) |
| 252 | { | 227 | { |
| 253 | int rc; | 228 | int rc; |
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index d6ac1b261dd9..9a7f247e8ac1 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
| @@ -341,6 +341,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work) | |||
| 341 | p_slot->state = POWERON_STATE; | 341 | p_slot->state = POWERON_STATE; |
| 342 | break; | 342 | break; |
| 343 | default: | 343 | default: |
| 344 | kfree(info); | ||
| 344 | goto out; | 345 | goto out; |
| 345 | } | 346 | } |
| 346 | queue_work(pciehp_wq, &info->work); | 347 | queue_work(pciehp_wq, &info->work); |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 10040d58c8ef..40b48f569b1e 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
| @@ -492,6 +492,7 @@ int pciehp_power_on_slot(struct slot * slot) | |||
| 492 | u16 slot_cmd; | 492 | u16 slot_cmd; |
| 493 | u16 cmd_mask; | 493 | u16 cmd_mask; |
| 494 | u16 slot_status; | 494 | u16 slot_status; |
| 495 | u16 lnk_status; | ||
| 495 | int retval = 0; | 496 | int retval = 0; |
| 496 | 497 | ||
| 497 | /* Clear sticky power-fault bit from previous power failures */ | 498 | /* Clear sticky power-fault bit from previous power failures */ |
| @@ -523,6 +524,14 @@ int pciehp_power_on_slot(struct slot * slot) | |||
| 523 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, | 524 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
| 524 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); | 525 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); |
| 525 | 526 | ||
| 527 | retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); | ||
| 528 | if (retval) { | ||
| 529 | ctrl_err(ctrl, "%s: Cannot read LNKSTA register\n", | ||
| 530 | __func__); | ||
| 531 | return retval; | ||
| 532 | } | ||
| 533 | pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status); | ||
| 534 | |||
| 526 | return retval; | 535 | return retval; |
| 527 | } | 536 | } |
| 528 | 537 | ||
| @@ -610,37 +619,6 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
| 610 | return IRQ_HANDLED; | 619 | return IRQ_HANDLED; |
| 611 | } | 620 | } |
| 612 | 621 | ||
| 613 | int pciehp_get_max_link_speed(struct slot *slot, enum pci_bus_speed *value) | ||
| 614 | { | ||
| 615 | struct controller *ctrl = slot->ctrl; | ||
| 616 | enum pcie_link_speed lnk_speed; | ||
| 617 | u32 lnk_cap; | ||
| 618 | int retval = 0; | ||
| 619 | |||
| 620 | retval = pciehp_readl(ctrl, PCI_EXP_LNKCAP, &lnk_cap); | ||
| 621 | if (retval) { | ||
| 622 | ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__); | ||
| 623 | return retval; | ||
| 624 | } | ||
| 625 | |||
| 626 | switch (lnk_cap & 0x000F) { | ||
| 627 | case 1: | ||
| 628 | lnk_speed = PCIE_2_5GB; | ||
| 629 | break; | ||
| 630 | case 2: | ||
| 631 | lnk_speed = PCIE_5_0GB; | ||
| 632 | break; | ||
| 633 | default: | ||
| 634 | lnk_speed = PCIE_LNK_SPEED_UNKNOWN; | ||
| 635 | break; | ||
| 636 | } | ||
| 637 | |||
| 638 | *value = lnk_speed; | ||
| 639 | ctrl_dbg(ctrl, "Max link speed = %d\n", lnk_speed); | ||
| 640 | |||
| 641 | return retval; | ||
| 642 | } | ||
| 643 | |||
| 644 | int pciehp_get_max_lnk_width(struct slot *slot, | 622 | int pciehp_get_max_lnk_width(struct slot *slot, |
| 645 | enum pcie_link_width *value) | 623 | enum pcie_link_width *value) |
| 646 | { | 624 | { |
| @@ -691,38 +669,6 @@ int pciehp_get_max_lnk_width(struct slot *slot, | |||
| 691 | return retval; | 669 | return retval; |
| 692 | } | 670 | } |
| 693 | 671 | ||
| 694 | int pciehp_get_cur_link_speed(struct slot *slot, enum pci_bus_speed *value) | ||
| 695 | { | ||
| 696 | struct controller *ctrl = slot->ctrl; | ||
| 697 | enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN; | ||
| 698 | int retval = 0; | ||
| 699 | u16 lnk_status; | ||
| 700 | |||
| 701 | retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); | ||
| 702 | if (retval) { | ||
| 703 | ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n", | ||
| 704 | __func__); | ||
| 705 | return retval; | ||
| 706 | } | ||
| 707 | |||
| 708 | switch (lnk_status & PCI_EXP_LNKSTA_CLS) { | ||
| 709 | case 1: | ||
| 710 | lnk_speed = PCIE_2_5GB; | ||
| 711 | break; | ||
| 712 | case 2: | ||
| 713 | lnk_speed = PCIE_5_0GB; | ||
| 714 | break; | ||
| 715 | default: | ||
| 716 | lnk_speed = PCIE_LNK_SPEED_UNKNOWN; | ||
| 717 | break; | ||
| 718 | } | ||
| 719 | |||
| 720 | *value = lnk_speed; | ||
| 721 | ctrl_dbg(ctrl, "Current link speed = %d\n", lnk_speed); | ||
| 722 | |||
| 723 | return retval; | ||
| 724 | } | ||
| 725 | |||
| 726 | int pciehp_get_cur_lnk_width(struct slot *slot, | 672 | int pciehp_get_cur_lnk_width(struct slot *slot, |
| 727 | enum pcie_link_width *value) | 673 | enum pcie_link_width *value) |
| 728 | { | 674 | { |
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 21733108adde..0a16444c14c9 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c | |||
| @@ -53,17 +53,15 @@ static int __ref pciehp_add_bridge(struct pci_dev *dev) | |||
| 53 | busnr = pci_scan_bridge(parent, dev, busnr, pass); | 53 | busnr = pci_scan_bridge(parent, dev, busnr, pass); |
| 54 | if (!dev->subordinate) | 54 | if (!dev->subordinate) |
| 55 | return -1; | 55 | return -1; |
| 56 | pci_bus_size_bridges(dev->subordinate); | 56 | |
| 57 | pci_bus_assign_resources(parent); | ||
| 58 | pci_enable_bridges(parent); | ||
| 59 | pci_bus_add_devices(parent); | ||
| 60 | return 0; | 57 | return 0; |
| 61 | } | 58 | } |
| 62 | 59 | ||
| 63 | int pciehp_configure_device(struct slot *p_slot) | 60 | int pciehp_configure_device(struct slot *p_slot) |
| 64 | { | 61 | { |
| 65 | struct pci_dev *dev; | 62 | struct pci_dev *dev; |
| 66 | struct pci_bus *parent = p_slot->ctrl->pcie->port->subordinate; | 63 | struct pci_dev *bridge = p_slot->ctrl->pcie->port; |
| 64 | struct pci_bus *parent = bridge->subordinate; | ||
| 67 | int num, fn; | 65 | int num, fn; |
| 68 | struct controller *ctrl = p_slot->ctrl; | 66 | struct controller *ctrl = p_slot->ctrl; |
| 69 | 67 | ||
| @@ -96,12 +94,25 @@ int pciehp_configure_device(struct slot *p_slot) | |||
| 96 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { | 94 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { |
| 97 | pciehp_add_bridge(dev); | 95 | pciehp_add_bridge(dev); |
| 98 | } | 96 | } |
| 97 | pci_dev_put(dev); | ||
| 98 | } | ||
| 99 | |||
| 100 | pci_assign_unassigned_bridge_resources(bridge); | ||
| 101 | |||
| 102 | for (fn = 0; fn < 8; fn++) { | ||
| 103 | dev = pci_get_slot(parent, PCI_DEVFN(0, fn)); | ||
| 104 | if (!dev) | ||
| 105 | continue; | ||
| 106 | if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | ||
| 107 | pci_dev_put(dev); | ||
| 108 | continue; | ||
| 109 | } | ||
| 99 | pci_configure_slot(dev); | 110 | pci_configure_slot(dev); |
| 100 | pci_dev_put(dev); | 111 | pci_dev_put(dev); |
| 101 | } | 112 | } |
| 102 | 113 | ||
| 103 | pci_bus_assign_resources(parent); | ||
| 104 | pci_bus_add_devices(parent); | 114 | pci_bus_add_devices(parent); |
| 115 | |||
| 105 | return 0; | 116 | return 0; |
| 106 | } | 117 | } |
| 107 | 118 | ||
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index c159223389ec..dcaae725fd79 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c | |||
| @@ -130,10 +130,9 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value) | |||
| 130 | return 0; | 130 | return 0; |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | 133 | static enum pci_bus_speed get_max_bus_speed(struct slot *slot) |
| 134 | { | 134 | { |
| 135 | struct slot *slot = (struct slot *)hotplug_slot->private; | 135 | enum pci_bus_speed speed; |
| 136 | |||
| 137 | switch (slot->type) { | 136 | switch (slot->type) { |
| 138 | case 1: | 137 | case 1: |
| 139 | case 2: | 138 | case 2: |
| @@ -141,30 +140,30 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe | |||
| 141 | case 4: | 140 | case 4: |
| 142 | case 5: | 141 | case 5: |
| 143 | case 6: | 142 | case 6: |
| 144 | *value = PCI_SPEED_33MHz; /* speed for case 1-6 */ | 143 | speed = PCI_SPEED_33MHz; /* speed for case 1-6 */ |
| 145 | break; | 144 | break; |
| 146 | case 7: | 145 | case 7: |
| 147 | case 8: | 146 | case 8: |
| 148 | *value = PCI_SPEED_66MHz; | 147 | speed = PCI_SPEED_66MHz; |
| 149 | break; | 148 | break; |
| 150 | case 11: | 149 | case 11: |
| 151 | case 14: | 150 | case 14: |
| 152 | *value = PCI_SPEED_66MHz_PCIX; | 151 | speed = PCI_SPEED_66MHz_PCIX; |
| 153 | break; | 152 | break; |
| 154 | case 12: | 153 | case 12: |
| 155 | case 15: | 154 | case 15: |
| 156 | *value = PCI_SPEED_100MHz_PCIX; | 155 | speed = PCI_SPEED_100MHz_PCIX; |
| 157 | break; | 156 | break; |
| 158 | case 13: | 157 | case 13: |
| 159 | case 16: | 158 | case 16: |
| 160 | *value = PCI_SPEED_133MHz_PCIX; | 159 | speed = PCI_SPEED_133MHz_PCIX; |
| 161 | break; | 160 | break; |
| 162 | default: | 161 | default: |
| 163 | *value = PCI_SPEED_UNKNOWN; | 162 | speed = PCI_SPEED_UNKNOWN; |
| 164 | break; | 163 | break; |
| 165 | |||
| 166 | } | 164 | } |
| 167 | return 0; | 165 | |
| 166 | return speed; | ||
| 168 | } | 167 | } |
| 169 | 168 | ||
| 170 | static int get_children_props(struct device_node *dn, const int **drc_indexes, | 169 | static int get_children_props(struct device_node *dn, const int **drc_indexes, |
| @@ -408,6 +407,8 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) | |||
| 408 | slot->state = NOT_VALID; | 407 | slot->state = NOT_VALID; |
| 409 | return -EINVAL; | 408 | return -EINVAL; |
| 410 | } | 409 | } |
| 410 | |||
| 411 | slot->bus->max_bus_speed = get_max_bus_speed(slot); | ||
| 411 | return 0; | 412 | return 0; |
| 412 | } | 413 | } |
| 413 | 414 | ||
| @@ -429,7 +430,6 @@ struct hotplug_slot_ops rpaphp_hotplug_slot_ops = { | |||
| 429 | .get_power_status = get_power_status, | 430 | .get_power_status = get_power_status, |
| 430 | .get_attention_status = get_attention_status, | 431 | .get_attention_status = get_attention_status, |
| 431 | .get_adapter_status = get_adapter_status, | 432 | .get_adapter_status = get_adapter_status, |
| 432 | .get_max_bus_speed = get_max_bus_speed, | ||
| 433 | }; | 433 | }; |
| 434 | 434 | ||
| 435 | module_init(rpaphp_init); | 435 | module_init(rpaphp_init); |
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 8e210cd76e55..d2627e1c3ac1 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
| @@ -333,8 +333,6 @@ struct hpc_ops { | |||
| 333 | int (*set_attention_status)(struct slot *slot, u8 status); | 333 | int (*set_attention_status)(struct slot *slot, u8 status); |
| 334 | int (*get_latch_status)(struct slot *slot, u8 *status); | 334 | int (*get_latch_status)(struct slot *slot, u8 *status); |
| 335 | int (*get_adapter_status)(struct slot *slot, u8 *status); | 335 | int (*get_adapter_status)(struct slot *slot, u8 *status); |
| 336 | int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed); | ||
| 337 | int (*get_cur_bus_speed)(struct slot *slot, enum pci_bus_speed *speed); | ||
| 338 | int (*get_adapter_speed)(struct slot *slot, enum pci_bus_speed *speed); | 336 | int (*get_adapter_speed)(struct slot *slot, enum pci_bus_speed *speed); |
| 339 | int (*get_mode1_ECC_cap)(struct slot *slot, u8 *mode); | 337 | int (*get_mode1_ECC_cap)(struct slot *slot, u8 *mode); |
| 340 | int (*get_prog_int)(struct slot *slot, u8 *prog_int); | 338 | int (*get_prog_int)(struct slot *slot, u8 *prog_int); |
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 8a520a3d0f59..a5062297f488 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c | |||
| @@ -65,8 +65,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value); | |||
| 65 | static int get_attention_status (struct hotplug_slot *slot, u8 *value); | 65 | static int get_attention_status (struct hotplug_slot *slot, u8 *value); |
| 66 | static int get_latch_status (struct hotplug_slot *slot, u8 *value); | 66 | static int get_latch_status (struct hotplug_slot *slot, u8 *value); |
| 67 | static int get_adapter_status (struct hotplug_slot *slot, u8 *value); | 67 | static int get_adapter_status (struct hotplug_slot *slot, u8 *value); |
| 68 | static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
| 69 | static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
| 70 | 68 | ||
| 71 | static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { | 69 | static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { |
| 72 | .set_attention_status = set_attention_status, | 70 | .set_attention_status = set_attention_status, |
| @@ -76,8 +74,6 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { | |||
| 76 | .get_attention_status = get_attention_status, | 74 | .get_attention_status = get_attention_status, |
| 77 | .get_latch_status = get_latch_status, | 75 | .get_latch_status = get_latch_status, |
| 78 | .get_adapter_status = get_adapter_status, | 76 | .get_adapter_status = get_adapter_status, |
| 79 | .get_max_bus_speed = get_max_bus_speed, | ||
| 80 | .get_cur_bus_speed = get_cur_bus_speed, | ||
| 81 | }; | 77 | }; |
| 82 | 78 | ||
| 83 | /** | 79 | /** |
| @@ -279,37 +275,6 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) | |||
| 279 | return 0; | 275 | return 0; |
| 280 | } | 276 | } |
| 281 | 277 | ||
| 282 | static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, | ||
| 283 | enum pci_bus_speed *value) | ||
| 284 | { | ||
| 285 | struct slot *slot = get_slot(hotplug_slot); | ||
| 286 | int retval; | ||
| 287 | |||
| 288 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | ||
| 289 | __func__, slot_name(slot)); | ||
| 290 | |||
| 291 | retval = slot->hpc_ops->get_max_bus_speed(slot, value); | ||
| 292 | if (retval < 0) | ||
| 293 | *value = PCI_SPEED_UNKNOWN; | ||
| 294 | |||
| 295 | return 0; | ||
| 296 | } | ||
| 297 | |||
| 298 | static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | ||
| 299 | { | ||
| 300 | struct slot *slot = get_slot(hotplug_slot); | ||
| 301 | int retval; | ||
| 302 | |||
| 303 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | ||
| 304 | __func__, slot_name(slot)); | ||
| 305 | |||
| 306 | retval = slot->hpc_ops->get_cur_bus_speed(slot, value); | ||
| 307 | if (retval < 0) | ||
| 308 | *value = PCI_SPEED_UNKNOWN; | ||
| 309 | |||
| 310 | return 0; | ||
| 311 | } | ||
| 312 | |||
| 313 | static int is_shpc_capable(struct pci_dev *dev) | 278 | static int is_shpc_capable(struct pci_dev *dev) |
| 314 | { | 279 | { |
| 315 | if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device == | 280 | if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device == |
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index b8ab2796e66a..3bba0c0888ff 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
| @@ -285,17 +285,8 @@ static int board_added(struct slot *p_slot) | |||
| 285 | return WRONG_BUS_FREQUENCY; | 285 | return WRONG_BUS_FREQUENCY; |
| 286 | } | 286 | } |
| 287 | 287 | ||
| 288 | rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bsp); | 288 | bsp = ctrl->pci_dev->bus->cur_bus_speed; |
| 289 | if (rc) { | 289 | msp = ctrl->pci_dev->bus->max_bus_speed; |
| 290 | ctrl_err(ctrl, "Can't get bus operation speed\n"); | ||
| 291 | return WRONG_BUS_FREQUENCY; | ||
| 292 | } | ||
| 293 | |||
| 294 | rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &msp); | ||
| 295 | if (rc) { | ||
| 296 | ctrl_err(ctrl, "Can't get max bus operation speed\n"); | ||
| 297 | msp = bsp; | ||
| 298 | } | ||
| 299 | 290 | ||
| 300 | /* Check if there are other slots or devices on the same bus */ | 291 | /* Check if there are other slots or devices on the same bus */ |
| 301 | if (!list_empty(&ctrl->pci_dev->subordinate->devices)) | 292 | if (!list_empty(&ctrl->pci_dev->subordinate->devices)) |
| @@ -462,6 +453,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work) | |||
| 462 | p_slot->state = POWERON_STATE; | 453 | p_slot->state = POWERON_STATE; |
| 463 | break; | 454 | break; |
| 464 | default: | 455 | default: |
| 456 | kfree(info); | ||
| 465 | goto out; | 457 | goto out; |
| 466 | } | 458 | } |
| 467 | queue_work(shpchp_wq, &info->work); | 459 | queue_work(shpchp_wq, &info->work); |
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 86dc39847769..5f5e8d2e3552 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
| @@ -660,6 +660,75 @@ static int hpc_slot_disable(struct slot * slot) | |||
| 660 | return retval; | 660 | return retval; |
| 661 | } | 661 | } |
| 662 | 662 | ||
| 663 | static int shpc_get_cur_bus_speed(struct controller *ctrl) | ||
| 664 | { | ||
| 665 | int retval = 0; | ||
| 666 | struct pci_bus *bus = ctrl->pci_dev->subordinate; | ||
| 667 | enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; | ||
| 668 | u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG); | ||
| 669 | u8 pi = shpc_readb(ctrl, PROG_INTERFACE); | ||
| 670 | u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); | ||
| 671 | |||
| 672 | if ((pi == 1) && (speed_mode > 4)) { | ||
| 673 | retval = -ENODEV; | ||
| 674 | goto out; | ||
| 675 | } | ||
| 676 | |||
| 677 | switch (speed_mode) { | ||
| 678 | case 0x0: | ||
| 679 | bus_speed = PCI_SPEED_33MHz; | ||
| 680 | break; | ||
| 681 | case 0x1: | ||
| 682 | bus_speed = PCI_SPEED_66MHz; | ||
| 683 | break; | ||
| 684 | case 0x2: | ||
| 685 | bus_speed = PCI_SPEED_66MHz_PCIX; | ||
| 686 | break; | ||
| 687 | case 0x3: | ||
| 688 | bus_speed = PCI_SPEED_100MHz_PCIX; | ||
| 689 | break; | ||
| 690 | case 0x4: | ||
| 691 | bus_speed = PCI_SPEED_133MHz_PCIX; | ||
| 692 | break; | ||
| 693 | case 0x5: | ||
| 694 | bus_speed = PCI_SPEED_66MHz_PCIX_ECC; | ||
| 695 | break; | ||
| 696 | case 0x6: | ||
| 697 | bus_speed = PCI_SPEED_100MHz_PCIX_ECC; | ||
| 698 | break; | ||
| 699 | case 0x7: | ||
| 700 | bus_speed = PCI_SPEED_133MHz_PCIX_ECC; | ||
| 701 | break; | ||
| 702 | case 0x8: | ||
| 703 | bus_speed = PCI_SPEED_66MHz_PCIX_266; | ||
| 704 | break; | ||
| 705 | case 0x9: | ||
| 706 | bus_speed = PCI_SPEED_100MHz_PCIX_266; | ||
| 707 | break; | ||
| 708 | case 0xa: | ||
| 709 | bus_speed = PCI_SPEED_133MHz_PCIX_266; | ||
| 710 | break; | ||
| 711 | case 0xb: | ||
| 712 | bus_speed = PCI_SPEED_66MHz_PCIX_533; | ||
| 713 | break; | ||
| 714 | case 0xc: | ||
| 715 | bus_speed = PCI_SPEED_100MHz_PCIX_533; | ||
| 716 | break; | ||
| 717 | case 0xd: | ||
| 718 | bus_speed = PCI_SPEED_133MHz_PCIX_533; | ||
| 719 | break; | ||
| 720 | default: | ||
| 721 | retval = -ENODEV; | ||
| 722 | break; | ||
| 723 | } | ||
| 724 | |||
| 725 | out: | ||
| 726 | bus->cur_bus_speed = bus_speed; | ||
| 727 | dbg("Current bus speed = %d\n", bus_speed); | ||
| 728 | return retval; | ||
| 729 | } | ||
| 730 | |||
| 731 | |||
| 663 | static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) | 732 | static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) |
| 664 | { | 733 | { |
| 665 | int retval; | 734 | int retval; |
| @@ -720,6 +789,8 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) | |||
| 720 | retval = shpc_write_cmd(slot, 0, cmd); | 789 | retval = shpc_write_cmd(slot, 0, cmd); |
| 721 | if (retval) | 790 | if (retval) |
| 722 | ctrl_err(ctrl, "%s: Write command failed!\n", __func__); | 791 | ctrl_err(ctrl, "%s: Write command failed!\n", __func__); |
| 792 | else | ||
| 793 | shpc_get_cur_bus_speed(ctrl); | ||
| 723 | 794 | ||
| 724 | return retval; | 795 | return retval; |
| 725 | } | 796 | } |
| @@ -803,10 +874,10 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) | |||
| 803 | return IRQ_HANDLED; | 874 | return IRQ_HANDLED; |
| 804 | } | 875 | } |
| 805 | 876 | ||
| 806 | static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) | 877 | static int shpc_get_max_bus_speed(struct controller *ctrl) |
| 807 | { | 878 | { |
| 808 | int retval = 0; | 879 | int retval = 0; |
| 809 | struct controller *ctrl = slot->ctrl; | 880 | struct pci_bus *bus = ctrl->pci_dev->subordinate; |
| 810 | enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; | 881 | enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; |
| 811 | u8 pi = shpc_readb(ctrl, PROG_INTERFACE); | 882 | u8 pi = shpc_readb(ctrl, PROG_INTERFACE); |
| 812 | u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1); | 883 | u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1); |
| @@ -842,79 +913,12 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) | |||
| 842 | retval = -ENODEV; | 913 | retval = -ENODEV; |
| 843 | } | 914 | } |
| 844 | 915 | ||
| 845 | *value = bus_speed; | 916 | bus->max_bus_speed = bus_speed; |
| 846 | ctrl_dbg(ctrl, "Max bus speed = %d\n", bus_speed); | 917 | ctrl_dbg(ctrl, "Max bus speed = %d\n", bus_speed); |
| 847 | 918 | ||
| 848 | return retval; | 919 | return retval; |
| 849 | } | 920 | } |
| 850 | 921 | ||
| 851 | static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) | ||
| 852 | { | ||
| 853 | int retval = 0; | ||
| 854 | struct controller *ctrl = slot->ctrl; | ||
| 855 | enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; | ||
| 856 | u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG); | ||
| 857 | u8 pi = shpc_readb(ctrl, PROG_INTERFACE); | ||
| 858 | u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); | ||
| 859 | |||
| 860 | if ((pi == 1) && (speed_mode > 4)) { | ||
| 861 | *value = PCI_SPEED_UNKNOWN; | ||
| 862 | return -ENODEV; | ||
| 863 | } | ||
| 864 | |||
| 865 | switch (speed_mode) { | ||
| 866 | case 0x0: | ||
| 867 | *value = PCI_SPEED_33MHz; | ||
| 868 | break; | ||
| 869 | case 0x1: | ||
| 870 | *value = PCI_SPEED_66MHz; | ||
| 871 | break; | ||
| 872 | case 0x2: | ||
| 873 | *value = PCI_SPEED_66MHz_PCIX; | ||
| 874 | break; | ||
| 875 | case 0x3: | ||
| 876 | *value = PCI_SPEED_100MHz_PCIX; | ||
| 877 | break; | ||
| 878 | case 0x4: | ||
| 879 | *value = PCI_SPEED_133MHz_PCIX; | ||
| 880 | break; | ||
| 881 | case 0x5: | ||
| 882 | *value = PCI_SPEED_66MHz_PCIX_ECC; | ||
| 883 | break; | ||
| 884 | case 0x6: | ||
| 885 | *value = PCI_SPEED_100MHz_PCIX_ECC; | ||
| 886 | break; | ||
| 887 | case 0x7: | ||
| 888 | *value = PCI_SPEED_133MHz_PCIX_ECC; | ||
| 889 | break; | ||
| 890 | case 0x8: | ||
| 891 | *value = PCI_SPEED_66MHz_PCIX_266; | ||
| 892 | break; | ||
| 893 | case 0x9: | ||
| 894 | *value = PCI_SPEED_100MHz_PCIX_266; | ||
| 895 | break; | ||
| 896 | case 0xa: | ||
| 897 | *value = PCI_SPEED_133MHz_PCIX_266; | ||
| 898 | break; | ||
| 899 | case 0xb: | ||
| 900 | *value = PCI_SPEED_66MHz_PCIX_533; | ||
| 901 | break; | ||
| 902 | case 0xc: | ||
| 903 | *value = PCI_SPEED_100MHz_PCIX_533; | ||
| 904 | break; | ||
| 905 | case 0xd: | ||
| 906 | *value = PCI_SPEED_133MHz_PCIX_533; | ||
| 907 | break; | ||
| 908 | default: | ||
| 909 | *value = PCI_SPEED_UNKNOWN; | ||
| 910 | retval = -ENODEV; | ||
| 911 | break; | ||
| 912 | } | ||
| 913 | |||
| 914 | ctrl_dbg(ctrl, "Current bus speed = %d\n", bus_speed); | ||
| 915 | return retval; | ||
| 916 | } | ||
| 917 | |||
| 918 | static struct hpc_ops shpchp_hpc_ops = { | 922 | static struct hpc_ops shpchp_hpc_ops = { |
| 919 | .power_on_slot = hpc_power_on_slot, | 923 | .power_on_slot = hpc_power_on_slot, |
| 920 | .slot_enable = hpc_slot_enable, | 924 | .slot_enable = hpc_slot_enable, |
| @@ -926,8 +930,6 @@ static struct hpc_ops shpchp_hpc_ops = { | |||
| 926 | .get_latch_status = hpc_get_latch_status, | 930 | .get_latch_status = hpc_get_latch_status, |
| 927 | .get_adapter_status = hpc_get_adapter_status, | 931 | .get_adapter_status = hpc_get_adapter_status, |
| 928 | 932 | ||
| 929 | .get_max_bus_speed = hpc_get_max_bus_speed, | ||
| 930 | .get_cur_bus_speed = hpc_get_cur_bus_speed, | ||
| 931 | .get_adapter_speed = hpc_get_adapter_speed, | 933 | .get_adapter_speed = hpc_get_adapter_speed, |
| 932 | .get_mode1_ECC_cap = hpc_get_mode1_ECC_cap, | 934 | .get_mode1_ECC_cap = hpc_get_mode1_ECC_cap, |
| 933 | .get_prog_int = hpc_get_prog_int, | 935 | .get_prog_int = hpc_get_prog_int, |
| @@ -1086,6 +1088,9 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) | |||
| 1086 | } | 1088 | } |
| 1087 | ctrl_dbg(ctrl, "HPC at %s irq=%x\n", pci_name(pdev), pdev->irq); | 1089 | ctrl_dbg(ctrl, "HPC at %s irq=%x\n", pci_name(pdev), pdev->irq); |
| 1088 | 1090 | ||
| 1091 | shpc_get_max_bus_speed(ctrl); | ||
| 1092 | shpc_get_cur_bus_speed(ctrl); | ||
| 1093 | |||
| 1089 | /* | 1094 | /* |
| 1090 | * If this is the first controller to be initialized, | 1095 | * If this is the first controller to be initialized, |
| 1091 | * initialize the shpchpd work queue | 1096 | * initialize the shpchpd work queue |
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c index 29fa9d26adae..071b7dc0094b 100644 --- a/drivers/pci/hotplug/shpchp_sysfs.c +++ b/drivers/pci/hotplug/shpchp_sysfs.c | |||
| @@ -47,8 +47,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha | |||
| 47 | bus = pdev->subordinate; | 47 | bus = pdev->subordinate; |
| 48 | 48 | ||
| 49 | out += sprintf(buf, "Free resources: memory\n"); | 49 | out += sprintf(buf, "Free resources: memory\n"); |
| 50 | for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) { | 50 | pci_bus_for_each_resource(bus, res, index) { |
| 51 | res = bus->resource[index]; | ||
| 52 | if (res && (res->flags & IORESOURCE_MEM) && | 51 | if (res && (res->flags & IORESOURCE_MEM) && |
| 53 | !(res->flags & IORESOURCE_PREFETCH)) { | 52 | !(res->flags & IORESOURCE_PREFETCH)) { |
| 54 | out += sprintf(out, "start = %8.8llx, " | 53 | out += sprintf(out, "start = %8.8llx, " |
| @@ -58,8 +57,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha | |||
| 58 | } | 57 | } |
| 59 | } | 58 | } |
| 60 | out += sprintf(out, "Free resources: prefetchable memory\n"); | 59 | out += sprintf(out, "Free resources: prefetchable memory\n"); |
| 61 | for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) { | 60 | pci_bus_for_each_resource(bus, res, index) { |
| 62 | res = bus->resource[index]; | ||
| 63 | if (res && (res->flags & IORESOURCE_MEM) && | 61 | if (res && (res->flags & IORESOURCE_MEM) && |
| 64 | (res->flags & IORESOURCE_PREFETCH)) { | 62 | (res->flags & IORESOURCE_PREFETCH)) { |
| 65 | out += sprintf(out, "start = %8.8llx, " | 63 | out += sprintf(out, "start = %8.8llx, " |
| @@ -69,8 +67,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha | |||
| 69 | } | 67 | } |
| 70 | } | 68 | } |
| 71 | out += sprintf(out, "Free resources: IO\n"); | 69 | out += sprintf(out, "Free resources: IO\n"); |
| 72 | for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) { | 70 | pci_bus_for_each_resource(bus, res, index) { |
| 73 | res = bus->resource[index]; | ||
| 74 | if (res && (res->flags & IORESOURCE_IO)) { | 71 | if (res && (res->flags & IORESOURCE_IO)) { |
| 75 | out += sprintf(out, "start = %8.8llx, " | 72 | out += sprintf(out, "start = %8.8llx, " |
| 76 | "length = %8.8llx\n", | 73 | "length = %8.8llx\n", |
diff --git a/drivers/pci/legacy.c b/drivers/pci/legacy.c deleted file mode 100644 index 871f65c15936..000000000000 --- a/drivers/pci/legacy.c +++ /dev/null | |||
| @@ -1,34 +0,0 @@ | |||
| 1 | #include <linux/init.h> | ||
| 2 | #include <linux/pci.h> | ||
| 3 | #include <linux/module.h> | ||
| 4 | #include <linux/interrupt.h> | ||
| 5 | #include "pci.h" | ||
| 6 | |||
| 7 | /** | ||
| 8 | * pci_find_device - begin or continue searching for a PCI device by vendor/device id | ||
| 9 | * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids | ||
| 10 | * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids | ||
| 11 | * @from: Previous PCI device found in search, or %NULL for new search. | ||
| 12 | * | ||
| 13 | * Iterates through the list of known PCI devices. If a PCI device is found | ||
| 14 | * with a matching @vendor and @device, a pointer to its device structure is | ||
| 15 | * returned. Otherwise, %NULL is returned. | ||
| 16 | * A new search is initiated by passing %NULL as the @from argument. | ||
| 17 | * Otherwise if @from is not %NULL, searches continue from next device | ||
| 18 | * on the global list. | ||
| 19 | * | ||
| 20 | * NOTE: Do not use this function any more; use pci_get_device() instead, as | ||
| 21 | * the PCI device returned by this function can disappear at any moment in | ||
| 22 | * time. | ||
| 23 | */ | ||
| 24 | struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, | ||
| 25 | struct pci_dev *from) | ||
| 26 | { | ||
| 27 | struct pci_dev *pdev; | ||
| 28 | |||
| 29 | pci_dev_get(from); | ||
| 30 | pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); | ||
| 31 | pci_dev_put(pdev); | ||
| 32 | return pdev; | ||
| 33 | } | ||
| 34 | EXPORT_SYMBOL(pci_find_device); | ||
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 7e2829538a4c..c0c73913833d 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
| @@ -16,8 +16,144 @@ | |||
| 16 | #include <acpi/acpi_bus.h> | 16 | #include <acpi/acpi_bus.h> |
| 17 | 17 | ||
| 18 | #include <linux/pci-acpi.h> | 18 | #include <linux/pci-acpi.h> |
| 19 | #include <linux/pm_runtime.h> | ||
| 19 | #include "pci.h" | 20 | #include "pci.h" |
| 20 | 21 | ||
| 22 | static DEFINE_MUTEX(pci_acpi_pm_notify_mtx); | ||
| 23 | |||
| 24 | /** | ||
| 25 | * pci_acpi_wake_bus - Wake-up notification handler for root buses. | ||
| 26 | * @handle: ACPI handle of a device the notification is for. | ||
| 27 | * @event: Type of the signaled event. | ||
| 28 | * @context: PCI root bus to wake up devices on. | ||
| 29 | */ | ||
| 30 | static void pci_acpi_wake_bus(acpi_handle handle, u32 event, void *context) | ||
| 31 | { | ||
| 32 | struct pci_bus *pci_bus = context; | ||
| 33 | |||
| 34 | if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_bus) | ||
| 35 | pci_pme_wakeup_bus(pci_bus); | ||
| 36 | } | ||
| 37 | |||
| 38 | /** | ||
| 39 | * pci_acpi_wake_dev - Wake-up notification handler for PCI devices. | ||
| 40 | * @handle: ACPI handle of a device the notification is for. | ||
| 41 | * @event: Type of the signaled event. | ||
| 42 | * @context: PCI device object to wake up. | ||
| 43 | */ | ||
| 44 | static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context) | ||
| 45 | { | ||
| 46 | struct pci_dev *pci_dev = context; | ||
| 47 | |||
| 48 | if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_dev) { | ||
| 49 | pci_check_pme_status(pci_dev); | ||
| 50 | pm_runtime_resume(&pci_dev->dev); | ||
| 51 | if (pci_dev->subordinate) | ||
| 52 | pci_pme_wakeup_bus(pci_dev->subordinate); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | /** | ||
| 57 | * add_pm_notifier - Register PM notifier for given ACPI device. | ||
| 58 | * @dev: ACPI device to add the notifier for. | ||
| 59 | * @context: PCI device or bus to check for PME status if an event is signaled. | ||
| 60 | * | ||
| 61 | * NOTE: @dev need not be a run-wake or wake-up device to be a valid source of | ||
| 62 | * PM wake-up events. For example, wake-up events may be generated for bridges | ||
| 63 | * if one of the devices below the bridge is signaling PME, even if the bridge | ||
| 64 | * itself doesn't have a wake-up GPE associated with it. | ||
| 65 | */ | ||
| 66 | static acpi_status add_pm_notifier(struct acpi_device *dev, | ||
| 67 | acpi_notify_handler handler, | ||
| 68 | void *context) | ||
| 69 | { | ||
| 70 | acpi_status status = AE_ALREADY_EXISTS; | ||
| 71 | |||
| 72 | mutex_lock(&pci_acpi_pm_notify_mtx); | ||
| 73 | |||
| 74 | if (dev->wakeup.flags.notifier_present) | ||
| 75 | goto out; | ||
| 76 | |||
| 77 | status = acpi_install_notify_handler(dev->handle, | ||
| 78 | ACPI_SYSTEM_NOTIFY, | ||
| 79 | handler, context); | ||
| 80 | if (ACPI_FAILURE(status)) | ||
| 81 | goto out; | ||
| 82 | |||
| 83 | dev->wakeup.flags.notifier_present = true; | ||
| 84 | |||
| 85 | out: | ||
| 86 | mutex_unlock(&pci_acpi_pm_notify_mtx); | ||
| 87 | return status; | ||
| 88 | } | ||
| 89 | |||
| 90 | /** | ||
| 91 | * remove_pm_notifier - Unregister PM notifier from given ACPI device. | ||
| 92 | * @dev: ACPI device to remove the notifier from. | ||
| 93 | */ | ||
| 94 | static acpi_status remove_pm_notifier(struct acpi_device *dev, | ||
| 95 | acpi_notify_handler handler) | ||
| 96 | { | ||
| 97 | acpi_status status = AE_BAD_PARAMETER; | ||
| 98 | |||
| 99 | mutex_lock(&pci_acpi_pm_notify_mtx); | ||
| 100 | |||
| 101 | if (!dev->wakeup.flags.notifier_present) | ||
| 102 | goto out; | ||
| 103 | |||
| 104 | status = acpi_remove_notify_handler(dev->handle, | ||
| 105 | ACPI_SYSTEM_NOTIFY, | ||
| 106 | handler); | ||
| 107 | if (ACPI_FAILURE(status)) | ||
| 108 | goto out; | ||
| 109 | |||
| 110 | dev->wakeup.flags.notifier_present = false; | ||
| 111 | |||
| 112 | out: | ||
| 113 | mutex_unlock(&pci_acpi_pm_notify_mtx); | ||
| 114 | return status; | ||
| 115 | } | ||
| 116 | |||
| 117 | /** | ||
| 118 | * pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus. | ||
| 119 | * @dev: ACPI device to add the notifier for. | ||
| 120 | * @pci_bus: PCI bus to walk checking for PME status if an event is signaled. | ||
| 121 | */ | ||
| 122 | acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, | ||
| 123 | struct pci_bus *pci_bus) | ||
| 124 | { | ||
| 125 | return add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus); | ||
| 126 | } | ||
| 127 | |||
| 128 | /** | ||
| 129 | * pci_acpi_remove_bus_pm_notifier - Unregister PCI bus PM notifier. | ||
| 130 | * @dev: ACPI device to remove the notifier from. | ||
| 131 | */ | ||
| 132 | acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev) | ||
| 133 | { | ||
| 134 | return remove_pm_notifier(dev, pci_acpi_wake_bus); | ||
| 135 | } | ||
| 136 | |||
| 137 | /** | ||
| 138 | * pci_acpi_add_pm_notifier - Register PM notifier for given PCI device. | ||
| 139 | * @dev: ACPI device to add the notifier for. | ||
| 140 | * @pci_dev: PCI device to check for the PME status if an event is signaled. | ||
| 141 | */ | ||
| 142 | acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, | ||
| 143 | struct pci_dev *pci_dev) | ||
| 144 | { | ||
| 145 | return add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev); | ||
| 146 | } | ||
| 147 | |||
| 148 | /** | ||
| 149 | * pci_acpi_remove_pm_notifier - Unregister PCI device PM notifier. | ||
| 150 | * @dev: ACPI device to remove the notifier from. | ||
| 151 | */ | ||
| 152 | acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev) | ||
| 153 | { | ||
| 154 | return remove_pm_notifier(dev, pci_acpi_wake_dev); | ||
| 155 | } | ||
| 156 | |||
| 21 | /* | 157 | /* |
| 22 | * _SxD returns the D-state with the highest power | 158 | * _SxD returns the D-state with the highest power |
| 23 | * (lowest D-state number) supported in the S-state "x". | 159 | * (lowest D-state number) supported in the S-state "x". |
| @@ -131,12 +267,87 @@ static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable) | |||
| 131 | return 0; | 267 | return 0; |
| 132 | } | 268 | } |
| 133 | 269 | ||
| 270 | /** | ||
| 271 | * acpi_dev_run_wake - Enable/disable wake-up for given device. | ||
| 272 | * @phys_dev: Device to enable/disable the platform to wake-up the system for. | ||
| 273 | * @enable: Whether enable or disable the wake-up functionality. | ||
| 274 | * | ||
| 275 | * Find the ACPI device object corresponding to @pci_dev and try to | ||
| 276 | * enable/disable the GPE associated with it. | ||
| 277 | */ | ||
| 278 | static int acpi_dev_run_wake(struct device *phys_dev, bool enable) | ||
| 279 | { | ||
| 280 | struct acpi_device *dev; | ||
| 281 | acpi_handle handle; | ||
| 282 | int error = -ENODEV; | ||
| 283 | |||
| 284 | if (!device_run_wake(phys_dev)) | ||
| 285 | return -EINVAL; | ||
| 286 | |||
| 287 | handle = DEVICE_ACPI_HANDLE(phys_dev); | ||
| 288 | if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &dev))) { | ||
| 289 | dev_dbg(phys_dev, "ACPI handle has no context in %s!\n", | ||
| 290 | __func__); | ||
| 291 | return -ENODEV; | ||
| 292 | } | ||
| 293 | |||
| 294 | if (enable) { | ||
| 295 | if (!dev->wakeup.run_wake_count++) { | ||
| 296 | acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0); | ||
| 297 | acpi_enable_gpe(dev->wakeup.gpe_device, | ||
| 298 | dev->wakeup.gpe_number, | ||
| 299 | ACPI_GPE_TYPE_RUNTIME); | ||
| 300 | } | ||
| 301 | } else if (dev->wakeup.run_wake_count > 0) { | ||
| 302 | if (!--dev->wakeup.run_wake_count) { | ||
| 303 | acpi_disable_gpe(dev->wakeup.gpe_device, | ||
| 304 | dev->wakeup.gpe_number, | ||
| 305 | ACPI_GPE_TYPE_RUNTIME); | ||
| 306 | acpi_disable_wakeup_device_power(dev); | ||
| 307 | } | ||
| 308 | } else { | ||
| 309 | error = -EALREADY; | ||
| 310 | } | ||
| 311 | |||
| 312 | return error; | ||
| 313 | } | ||
| 314 | |||
| 315 | static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable) | ||
| 316 | { | ||
| 317 | while (bus->parent) { | ||
| 318 | struct pci_dev *bridge = bus->self; | ||
| 319 | |||
| 320 | if (bridge->pme_interrupt) | ||
| 321 | return; | ||
| 322 | if (!acpi_dev_run_wake(&bridge->dev, enable)) | ||
| 323 | return; | ||
| 324 | bus = bus->parent; | ||
| 325 | } | ||
| 326 | |||
| 327 | /* We have reached the root bus. */ | ||
| 328 | if (bus->bridge) | ||
| 329 | acpi_dev_run_wake(bus->bridge, enable); | ||
| 330 | } | ||
| 331 | |||
| 332 | static int acpi_pci_run_wake(struct pci_dev *dev, bool enable) | ||
| 333 | { | ||
| 334 | if (dev->pme_interrupt) | ||
| 335 | return 0; | ||
| 336 | |||
| 337 | if (!acpi_dev_run_wake(&dev->dev, enable)) | ||
| 338 | return 0; | ||
| 339 | |||
| 340 | acpi_pci_propagate_run_wake(dev->bus, enable); | ||
| 341 | return 0; | ||
| 342 | } | ||
| 343 | |||
| 134 | static struct pci_platform_pm_ops acpi_pci_platform_pm = { | 344 | static struct pci_platform_pm_ops acpi_pci_platform_pm = { |
| 135 | .is_manageable = acpi_pci_power_manageable, | 345 | .is_manageable = acpi_pci_power_manageable, |
| 136 | .set_state = acpi_pci_set_power_state, | 346 | .set_state = acpi_pci_set_power_state, |
| 137 | .choose_state = acpi_pci_choose_state, | 347 | .choose_state = acpi_pci_choose_state, |
| 138 | .can_wakeup = acpi_pci_can_wakeup, | 348 | .can_wakeup = acpi_pci_can_wakeup, |
| 139 | .sleep_wake = acpi_pci_sleep_wake, | 349 | .sleep_wake = acpi_pci_sleep_wake, |
| 350 | .run_wake = acpi_pci_run_wake, | ||
| 140 | }; | 351 | }; |
| 141 | 352 | ||
| 142 | /* ACPI bus type */ | 353 | /* ACPI bus type */ |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index e5d47be3c6d7..f9a0aec3abcf 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
| 19 | #include <linux/cpu.h> | 19 | #include <linux/cpu.h> |
| 20 | #include <linux/pm_runtime.h> | ||
| 20 | #include "pci.h" | 21 | #include "pci.h" |
| 21 | 22 | ||
| 22 | struct pci_dynid { | 23 | struct pci_dynid { |
| @@ -404,6 +405,35 @@ static void pci_device_shutdown(struct device *dev) | |||
| 404 | pci_msix_shutdown(pci_dev); | 405 | pci_msix_shutdown(pci_dev); |
| 405 | } | 406 | } |
| 406 | 407 | ||
| 408 | #ifdef CONFIG_PM_OPS | ||
| 409 | |||
| 410 | /* Auxiliary functions used for system resume and run-time resume. */ | ||
| 411 | |||
| 412 | /** | ||
| 413 | * pci_restore_standard_config - restore standard config registers of PCI device | ||
| 414 | * @pci_dev: PCI device to handle | ||
| 415 | */ | ||
| 416 | static int pci_restore_standard_config(struct pci_dev *pci_dev) | ||
| 417 | { | ||
| 418 | pci_update_current_state(pci_dev, PCI_UNKNOWN); | ||
| 419 | |||
| 420 | if (pci_dev->current_state != PCI_D0) { | ||
| 421 | int error = pci_set_power_state(pci_dev, PCI_D0); | ||
| 422 | if (error) | ||
| 423 | return error; | ||
| 424 | } | ||
| 425 | |||
| 426 | return pci_restore_state(pci_dev); | ||
| 427 | } | ||
| 428 | |||
| 429 | static void pci_pm_default_resume_early(struct pci_dev *pci_dev) | ||
| 430 | { | ||
| 431 | pci_restore_standard_config(pci_dev); | ||
| 432 | pci_fixup_device(pci_fixup_resume_early, pci_dev); | ||
| 433 | } | ||
| 434 | |||
| 435 | #endif | ||
| 436 | |||
| 407 | #ifdef CONFIG_PM_SLEEP | 437 | #ifdef CONFIG_PM_SLEEP |
| 408 | 438 | ||
| 409 | /* | 439 | /* |
| @@ -520,29 +550,6 @@ static int pci_legacy_resume(struct device *dev) | |||
| 520 | 550 | ||
| 521 | /* Auxiliary functions used by the new power management framework */ | 551 | /* Auxiliary functions used by the new power management framework */ |
| 522 | 552 | ||
| 523 | /** | ||
| 524 | * pci_restore_standard_config - restore standard config registers of PCI device | ||
| 525 | * @pci_dev: PCI device to handle | ||
| 526 | */ | ||
| 527 | static int pci_restore_standard_config(struct pci_dev *pci_dev) | ||
| 528 | { | ||
| 529 | pci_update_current_state(pci_dev, PCI_UNKNOWN); | ||
| 530 | |||
| 531 | if (pci_dev->current_state != PCI_D0) { | ||
| 532 | int error = pci_set_power_state(pci_dev, PCI_D0); | ||
| 533 | if (error) | ||
| 534 | return error; | ||
| 535 | } | ||
| 536 | |||
| 537 | return pci_restore_state(pci_dev); | ||
| 538 | } | ||
| 539 | |||
| 540 | static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev) | ||
| 541 | { | ||
| 542 | pci_restore_standard_config(pci_dev); | ||
| 543 | pci_fixup_device(pci_fixup_resume_early, pci_dev); | ||
| 544 | } | ||
| 545 | |||
| 546 | static void pci_pm_default_resume(struct pci_dev *pci_dev) | 553 | static void pci_pm_default_resume(struct pci_dev *pci_dev) |
| 547 | { | 554 | { |
| 548 | pci_fixup_device(pci_fixup_resume, pci_dev); | 555 | pci_fixup_device(pci_fixup_resume, pci_dev); |
| @@ -581,6 +588,17 @@ static int pci_pm_prepare(struct device *dev) | |||
| 581 | struct device_driver *drv = dev->driver; | 588 | struct device_driver *drv = dev->driver; |
| 582 | int error = 0; | 589 | int error = 0; |
| 583 | 590 | ||
| 591 | /* | ||
| 592 | * PCI devices suspended at run time need to be resumed at this | ||
| 593 | * point, because in general it is necessary to reconfigure them for | ||
| 594 | * system suspend. Namely, if the device is supposed to wake up the | ||
| 595 | * system from the sleep state, we may need to reconfigure it for this | ||
| 596 | * purpose. In turn, if the device is not supposed to wake up the | ||
| 597 | * system from the sleep state, we'll have to prevent it from signaling | ||
| 598 | * wake-up. | ||
| 599 | */ | ||
| 600 | pm_runtime_resume(dev); | ||
| 601 | |||
| 584 | if (drv && drv->pm && drv->pm->prepare) | 602 | if (drv && drv->pm && drv->pm->prepare) |
| 585 | error = drv->pm->prepare(dev); | 603 | error = drv->pm->prepare(dev); |
| 586 | 604 | ||
| @@ -595,6 +613,13 @@ static void pci_pm_complete(struct device *dev) | |||
| 595 | drv->pm->complete(dev); | 613 | drv->pm->complete(dev); |
| 596 | } | 614 | } |
| 597 | 615 | ||
| 616 | #else /* !CONFIG_PM_SLEEP */ | ||
| 617 | |||
| 618 | #define pci_pm_prepare NULL | ||
| 619 | #define pci_pm_complete NULL | ||
| 620 | |||
| 621 | #endif /* !CONFIG_PM_SLEEP */ | ||
| 622 | |||
| 598 | #ifdef CONFIG_SUSPEND | 623 | #ifdef CONFIG_SUSPEND |
| 599 | 624 | ||
| 600 | static int pci_pm_suspend(struct device *dev) | 625 | static int pci_pm_suspend(struct device *dev) |
| @@ -681,7 +706,7 @@ static int pci_pm_resume_noirq(struct device *dev) | |||
| 681 | struct device_driver *drv = dev->driver; | 706 | struct device_driver *drv = dev->driver; |
| 682 | int error = 0; | 707 | int error = 0; |
| 683 | 708 | ||
| 684 | pci_pm_default_resume_noirq(pci_dev); | 709 | pci_pm_default_resume_early(pci_dev); |
| 685 | 710 | ||
| 686 | if (pci_has_legacy_pm_support(pci_dev)) | 711 | if (pci_has_legacy_pm_support(pci_dev)) |
| 687 | return pci_legacy_resume_early(dev); | 712 | return pci_legacy_resume_early(dev); |
| @@ -879,7 +904,7 @@ static int pci_pm_restore_noirq(struct device *dev) | |||
| 879 | struct device_driver *drv = dev->driver; | 904 | struct device_driver *drv = dev->driver; |
| 880 | int error = 0; | 905 | int error = 0; |
| 881 | 906 | ||
| 882 | pci_pm_default_resume_noirq(pci_dev); | 907 | pci_pm_default_resume_early(pci_dev); |
| 883 | 908 | ||
| 884 | if (pci_has_legacy_pm_support(pci_dev)) | 909 | if (pci_has_legacy_pm_support(pci_dev)) |
| 885 | return pci_legacy_resume_early(dev); | 910 | return pci_legacy_resume_early(dev); |
| @@ -931,6 +956,84 @@ static int pci_pm_restore(struct device *dev) | |||
| 931 | 956 | ||
| 932 | #endif /* !CONFIG_HIBERNATION */ | 957 | #endif /* !CONFIG_HIBERNATION */ |
| 933 | 958 | ||
| 959 | #ifdef CONFIG_PM_RUNTIME | ||
| 960 | |||
| 961 | static int pci_pm_runtime_suspend(struct device *dev) | ||
| 962 | { | ||
| 963 | struct pci_dev *pci_dev = to_pci_dev(dev); | ||
| 964 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
| 965 | pci_power_t prev = pci_dev->current_state; | ||
| 966 | int error; | ||
| 967 | |||
| 968 | if (!pm || !pm->runtime_suspend) | ||
| 969 | return -ENOSYS; | ||
| 970 | |||
| 971 | error = pm->runtime_suspend(dev); | ||
| 972 | suspend_report_result(pm->runtime_suspend, error); | ||
| 973 | if (error) | ||
| 974 | return error; | ||
| 975 | |||
| 976 | pci_fixup_device(pci_fixup_suspend, pci_dev); | ||
| 977 | |||
| 978 | if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 | ||
| 979 | && pci_dev->current_state != PCI_UNKNOWN) { | ||
| 980 | WARN_ONCE(pci_dev->current_state != prev, | ||
| 981 | "PCI PM: State of device not saved by %pF\n", | ||
| 982 | pm->runtime_suspend); | ||
| 983 | return 0; | ||
| 984 | } | ||
| 985 | |||
| 986 | if (!pci_dev->state_saved) | ||
| 987 | pci_save_state(pci_dev); | ||
| 988 | |||
| 989 | pci_finish_runtime_suspend(pci_dev); | ||
| 990 | |||
| 991 | return 0; | ||
| 992 | } | ||
| 993 | |||
| 994 | static int pci_pm_runtime_resume(struct device *dev) | ||
| 995 | { | ||
| 996 | struct pci_dev *pci_dev = to_pci_dev(dev); | ||
| 997 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
| 998 | |||
| 999 | if (!pm || !pm->runtime_resume) | ||
| 1000 | return -ENOSYS; | ||
| 1001 | |||
| 1002 | pci_pm_default_resume_early(pci_dev); | ||
| 1003 | __pci_enable_wake(pci_dev, PCI_D0, true, false); | ||
| 1004 | pci_fixup_device(pci_fixup_resume, pci_dev); | ||
| 1005 | |||
| 1006 | return pm->runtime_resume(dev); | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | static int pci_pm_runtime_idle(struct device *dev) | ||
| 1010 | { | ||
| 1011 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
| 1012 | |||
| 1013 | if (!pm) | ||
| 1014 | return -ENOSYS; | ||
| 1015 | |||
| 1016 | if (pm->runtime_idle) { | ||
| 1017 | int ret = pm->runtime_idle(dev); | ||
| 1018 | if (ret) | ||
| 1019 | return ret; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | pm_runtime_suspend(dev); | ||
| 1023 | |||
| 1024 | return 0; | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | #else /* !CONFIG_PM_RUNTIME */ | ||
| 1028 | |||
| 1029 | #define pci_pm_runtime_suspend NULL | ||
| 1030 | #define pci_pm_runtime_resume NULL | ||
| 1031 | #define pci_pm_runtime_idle NULL | ||
| 1032 | |||
| 1033 | #endif /* !CONFIG_PM_RUNTIME */ | ||
| 1034 | |||
| 1035 | #ifdef CONFIG_PM_OPS | ||
| 1036 | |||
| 934 | const struct dev_pm_ops pci_dev_pm_ops = { | 1037 | const struct dev_pm_ops pci_dev_pm_ops = { |
| 935 | .prepare = pci_pm_prepare, | 1038 | .prepare = pci_pm_prepare, |
| 936 | .complete = pci_pm_complete, | 1039 | .complete = pci_pm_complete, |
| @@ -946,15 +1049,18 @@ const struct dev_pm_ops pci_dev_pm_ops = { | |||
| 946 | .thaw_noirq = pci_pm_thaw_noirq, | 1049 | .thaw_noirq = pci_pm_thaw_noirq, |
| 947 | .poweroff_noirq = pci_pm_poweroff_noirq, | 1050 | .poweroff_noirq = pci_pm_poweroff_noirq, |
| 948 | .restore_noirq = pci_pm_restore_noirq, | 1051 | .restore_noirq = pci_pm_restore_noirq, |
| 1052 | .runtime_suspend = pci_pm_runtime_suspend, | ||
| 1053 | .runtime_resume = pci_pm_runtime_resume, | ||
| 1054 | .runtime_idle = pci_pm_runtime_idle, | ||
| 949 | }; | 1055 | }; |
| 950 | 1056 | ||
| 951 | #define PCI_PM_OPS_PTR (&pci_dev_pm_ops) | 1057 | #define PCI_PM_OPS_PTR (&pci_dev_pm_ops) |
| 952 | 1058 | ||
| 953 | #else /* !CONFIG_PM_SLEEP */ | 1059 | #else /* !COMFIG_PM_OPS */ |
| 954 | 1060 | ||
| 955 | #define PCI_PM_OPS_PTR NULL | 1061 | #define PCI_PM_OPS_PTR NULL |
| 956 | 1062 | ||
| 957 | #endif /* !CONFIG_PM_SLEEP */ | 1063 | #endif /* !COMFIG_PM_OPS */ |
| 958 | 1064 | ||
| 959 | /** | 1065 | /** |
| 960 | * __pci_register_driver - register a new pci driver | 1066 | * __pci_register_driver - register a new pci driver |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 315fea47e784..f4a2738bf0bf 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
| @@ -19,8 +19,8 @@ | |||
| 19 | #include <linux/pci-aspm.h> | 19 | #include <linux/pci-aspm.h> |
| 20 | #include <linux/pm_wakeup.h> | 20 | #include <linux/pm_wakeup.h> |
| 21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
| 22 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ | ||
| 23 | #include <linux/device.h> | 22 | #include <linux/device.h> |
| 23 | #include <linux/pm_runtime.h> | ||
| 24 | #include <asm/setup.h> | 24 | #include <asm/setup.h> |
| 25 | #include "pci.h" | 25 | #include "pci.h" |
| 26 | 26 | ||
| @@ -29,6 +29,12 @@ const char *pci_power_names[] = { | |||
| 29 | }; | 29 | }; |
| 30 | EXPORT_SYMBOL_GPL(pci_power_names); | 30 | EXPORT_SYMBOL_GPL(pci_power_names); |
| 31 | 31 | ||
| 32 | int isa_dma_bridge_buggy; | ||
| 33 | EXPORT_SYMBOL(isa_dma_bridge_buggy); | ||
| 34 | |||
| 35 | int pci_pci_problems; | ||
| 36 | EXPORT_SYMBOL(pci_pci_problems); | ||
| 37 | |||
| 32 | unsigned int pci_pm_d3_delay; | 38 | unsigned int pci_pm_d3_delay; |
| 33 | 39 | ||
| 34 | static void pci_dev_d3_sleep(struct pci_dev *dev) | 40 | static void pci_dev_d3_sleep(struct pci_dev *dev) |
| @@ -380,10 +386,9 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res) | |||
| 380 | { | 386 | { |
| 381 | const struct pci_bus *bus = dev->bus; | 387 | const struct pci_bus *bus = dev->bus; |
| 382 | int i; | 388 | int i; |
| 383 | struct resource *best = NULL; | 389 | struct resource *best = NULL, *r; |
| 384 | 390 | ||
| 385 | for(i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | 391 | pci_bus_for_each_resource(bus, r, i) { |
| 386 | struct resource *r = bus->resource[i]; | ||
| 387 | if (!r) | 392 | if (!r) |
| 388 | continue; | 393 | continue; |
| 389 | if (res->start && !(res->start >= r->start && res->end <= r->end)) | 394 | if (res->start && !(res->start >= r->start && res->end <= r->end)) |
| @@ -457,6 +462,12 @@ static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable) | |||
| 457 | pci_platform_pm->sleep_wake(dev, enable) : -ENODEV; | 462 | pci_platform_pm->sleep_wake(dev, enable) : -ENODEV; |
| 458 | } | 463 | } |
| 459 | 464 | ||
| 465 | static inline int platform_pci_run_wake(struct pci_dev *dev, bool enable) | ||
| 466 | { | ||
| 467 | return pci_platform_pm ? | ||
| 468 | pci_platform_pm->run_wake(dev, enable) : -ENODEV; | ||
| 469 | } | ||
| 470 | |||
| 460 | /** | 471 | /** |
| 461 | * pci_raw_set_power_state - Use PCI PM registers to set the power state of | 472 | * pci_raw_set_power_state - Use PCI PM registers to set the power state of |
| 462 | * given PCI device | 473 | * given PCI device |
| @@ -1190,6 +1201,66 @@ int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state) | |||
| 1190 | } | 1201 | } |
| 1191 | 1202 | ||
| 1192 | /** | 1203 | /** |
| 1204 | * pci_check_pme_status - Check if given device has generated PME. | ||
| 1205 | * @dev: Device to check. | ||
| 1206 | * | ||
| 1207 | * Check the PME status of the device and if set, clear it and clear PME enable | ||
| 1208 | * (if set). Return 'true' if PME status and PME enable were both set or | ||
| 1209 | * 'false' otherwise. | ||
| 1210 | */ | ||
| 1211 | bool pci_check_pme_status(struct pci_dev *dev) | ||
| 1212 | { | ||
| 1213 | int pmcsr_pos; | ||
| 1214 | u16 pmcsr; | ||
| 1215 | bool ret = false; | ||
| 1216 | |||
| 1217 | if (!dev->pm_cap) | ||
| 1218 | return false; | ||
| 1219 | |||
| 1220 | pmcsr_pos = dev->pm_cap + PCI_PM_CTRL; | ||
| 1221 | pci_read_config_word(dev, pmcsr_pos, &pmcsr); | ||
| 1222 | if (!(pmcsr & PCI_PM_CTRL_PME_STATUS)) | ||
| 1223 | return false; | ||
| 1224 | |||
| 1225 | /* Clear PME status. */ | ||
| 1226 | pmcsr |= PCI_PM_CTRL_PME_STATUS; | ||
| 1227 | if (pmcsr & PCI_PM_CTRL_PME_ENABLE) { | ||
| 1228 | /* Disable PME to avoid interrupt flood. */ | ||
| 1229 | pmcsr &= ~PCI_PM_CTRL_PME_ENABLE; | ||
| 1230 | ret = true; | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | pci_write_config_word(dev, pmcsr_pos, pmcsr); | ||
| 1234 | |||
| 1235 | return ret; | ||
| 1236 | } | ||
| 1237 | |||
| 1238 | /** | ||
| 1239 | * pci_pme_wakeup - Wake up a PCI device if its PME Status bit is set. | ||
| 1240 | * @dev: Device to handle. | ||
| 1241 | * @ign: Ignored. | ||
| 1242 | * | ||
| 1243 | * Check if @dev has generated PME and queue a resume request for it in that | ||
| 1244 | * case. | ||
| 1245 | */ | ||
| 1246 | static int pci_pme_wakeup(struct pci_dev *dev, void *ign) | ||
| 1247 | { | ||
| 1248 | if (pci_check_pme_status(dev)) | ||
| 1249 | pm_request_resume(&dev->dev); | ||
| 1250 | return 0; | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | /** | ||
| 1254 | * pci_pme_wakeup_bus - Walk given bus and wake up devices on it, if necessary. | ||
| 1255 | * @bus: Top bus of the subtree to walk. | ||
| 1256 | */ | ||
| 1257 | void pci_pme_wakeup_bus(struct pci_bus *bus) | ||
| 1258 | { | ||
| 1259 | if (bus) | ||
| 1260 | pci_walk_bus(bus, pci_pme_wakeup, NULL); | ||
| 1261 | } | ||
| 1262 | |||
| 1263 | /** | ||
| 1193 | * pci_pme_capable - check the capability of PCI device to generate PME# | 1264 | * pci_pme_capable - check the capability of PCI device to generate PME# |
| 1194 | * @dev: PCI device to handle. | 1265 | * @dev: PCI device to handle. |
| 1195 | * @state: PCI state from which device will issue PME#. | 1266 | * @state: PCI state from which device will issue PME#. |
| @@ -1230,9 +1301,10 @@ void pci_pme_active(struct pci_dev *dev, bool enable) | |||
| 1230 | } | 1301 | } |
| 1231 | 1302 | ||
| 1232 | /** | 1303 | /** |
| 1233 | * pci_enable_wake - enable PCI device as wakeup event source | 1304 | * __pci_enable_wake - enable PCI device as wakeup event source |
| 1234 | * @dev: PCI device affected | 1305 | * @dev: PCI device affected |
| 1235 | * @state: PCI state from which device will issue wakeup events | 1306 | * @state: PCI state from which device will issue wakeup events |
| 1307 | * @runtime: True if the events are to be generated at run time | ||
| 1236 | * @enable: True to enable event generation; false to disable | 1308 | * @enable: True to enable event generation; false to disable |
| 1237 | * | 1309 | * |
| 1238 | * This enables the device as a wakeup event source, or disables it. | 1310 | * This enables the device as a wakeup event source, or disables it. |
| @@ -1248,11 +1320,12 @@ void pci_pme_active(struct pci_dev *dev, bool enable) | |||
| 1248 | * Error code depending on the platform is returned if both the platform and | 1320 | * Error code depending on the platform is returned if both the platform and |
| 1249 | * the native mechanism fail to enable the generation of wake-up events | 1321 | * the native mechanism fail to enable the generation of wake-up events |
| 1250 | */ | 1322 | */ |
| 1251 | int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable) | 1323 | int __pci_enable_wake(struct pci_dev *dev, pci_power_t state, |
| 1324 | bool runtime, bool enable) | ||
| 1252 | { | 1325 | { |
| 1253 | int ret = 0; | 1326 | int ret = 0; |
| 1254 | 1327 | ||
| 1255 | if (enable && !device_may_wakeup(&dev->dev)) | 1328 | if (enable && !runtime && !device_may_wakeup(&dev->dev)) |
| 1256 | return -EINVAL; | 1329 | return -EINVAL; |
| 1257 | 1330 | ||
| 1258 | /* Don't do the same thing twice in a row for one device. */ | 1331 | /* Don't do the same thing twice in a row for one device. */ |
| @@ -1272,19 +1345,24 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable) | |||
| 1272 | pci_pme_active(dev, true); | 1345 | pci_pme_active(dev, true); |
| 1273 | else | 1346 | else |
| 1274 | ret = 1; | 1347 | ret = 1; |
| 1275 | error = platform_pci_sleep_wake(dev, true); | 1348 | error = runtime ? platform_pci_run_wake(dev, true) : |
| 1349 | platform_pci_sleep_wake(dev, true); | ||
| 1276 | if (ret) | 1350 | if (ret) |
| 1277 | ret = error; | 1351 | ret = error; |
| 1278 | if (!ret) | 1352 | if (!ret) |
| 1279 | dev->wakeup_prepared = true; | 1353 | dev->wakeup_prepared = true; |
| 1280 | } else { | 1354 | } else { |
| 1281 | platform_pci_sleep_wake(dev, false); | 1355 | if (runtime) |
| 1356 | platform_pci_run_wake(dev, false); | ||
| 1357 | else | ||
| 1358 | platform_pci_sleep_wake(dev, false); | ||
| 1282 | pci_pme_active(dev, false); | 1359 | pci_pme_active(dev, false); |
| 1283 | dev->wakeup_prepared = false; | 1360 | dev->wakeup_prepared = false; |
| 1284 | } | 1361 | } |
| 1285 | 1362 | ||
| 1286 | return ret; | 1363 | return ret; |
| 1287 | } | 1364 | } |
| 1365 | EXPORT_SYMBOL(__pci_enable_wake); | ||
| 1288 | 1366 | ||
| 1289 | /** | 1367 | /** |
| 1290 | * pci_wake_from_d3 - enable/disable device to wake up from D3_hot or D3_cold | 1368 | * pci_wake_from_d3 - enable/disable device to wake up from D3_hot or D3_cold |
| @@ -1394,6 +1472,66 @@ int pci_back_from_sleep(struct pci_dev *dev) | |||
| 1394 | } | 1472 | } |
| 1395 | 1473 | ||
| 1396 | /** | 1474 | /** |
| 1475 | * pci_finish_runtime_suspend - Carry out PCI-specific part of runtime suspend. | ||
| 1476 | * @dev: PCI device being suspended. | ||
| 1477 | * | ||
| 1478 | * Prepare @dev to generate wake-up events at run time and put it into a low | ||
| 1479 | * power state. | ||
| 1480 | */ | ||
| 1481 | int pci_finish_runtime_suspend(struct pci_dev *dev) | ||
| 1482 | { | ||
| 1483 | pci_power_t target_state = pci_target_state(dev); | ||
| 1484 | int error; | ||
| 1485 | |||
| 1486 | if (target_state == PCI_POWER_ERROR) | ||
| 1487 | return -EIO; | ||
| 1488 | |||
| 1489 | __pci_enable_wake(dev, target_state, true, pci_dev_run_wake(dev)); | ||
| 1490 | |||
| 1491 | error = pci_set_power_state(dev, target_state); | ||
| 1492 | |||
| 1493 | if (error) | ||
| 1494 | __pci_enable_wake(dev, target_state, true, false); | ||
| 1495 | |||
| 1496 | return error; | ||
| 1497 | } | ||
| 1498 | |||
| 1499 | /** | ||
| 1500 | * pci_dev_run_wake - Check if device can generate run-time wake-up events. | ||
| 1501 | * @dev: Device to check. | ||
| 1502 | * | ||
| 1503 | * Return true if the device itself is cabable of generating wake-up events | ||
| 1504 | * (through the platform or using the native PCIe PME) or if the device supports | ||
| 1505 | * PME and one of its upstream bridges can generate wake-up events. | ||
| 1506 | */ | ||
| 1507 | bool pci_dev_run_wake(struct pci_dev *dev) | ||
| 1508 | { | ||
| 1509 | struct pci_bus *bus = dev->bus; | ||
| 1510 | |||
| 1511 | if (device_run_wake(&dev->dev)) | ||
| 1512 | return true; | ||
| 1513 | |||
| 1514 | if (!dev->pme_support) | ||
| 1515 | return false; | ||
| 1516 | |||
| 1517 | while (bus->parent) { | ||
| 1518 | struct pci_dev *bridge = bus->self; | ||
| 1519 | |||
| 1520 | if (device_run_wake(&bridge->dev)) | ||
| 1521 | return true; | ||
| 1522 | |||
| 1523 | bus = bus->parent; | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | /* We have reached the root bus. */ | ||
| 1527 | if (bus->bridge) | ||
| 1528 | return device_run_wake(bus->bridge); | ||
| 1529 | |||
| 1530 | return false; | ||
| 1531 | } | ||
| 1532 | EXPORT_SYMBOL_GPL(pci_dev_run_wake); | ||
| 1533 | |||
| 1534 | /** | ||
| 1397 | * pci_pm_init - Initialize PM functions of given PCI device | 1535 | * pci_pm_init - Initialize PM functions of given PCI device |
| 1398 | * @dev: PCI device to handle. | 1536 | * @dev: PCI device to handle. |
| 1399 | */ | 1537 | */ |
| @@ -2871,7 +3009,6 @@ EXPORT_SYMBOL(pci_save_state); | |||
| 2871 | EXPORT_SYMBOL(pci_restore_state); | 3009 | EXPORT_SYMBOL(pci_restore_state); |
| 2872 | EXPORT_SYMBOL(pci_pme_capable); | 3010 | EXPORT_SYMBOL(pci_pme_capable); |
| 2873 | EXPORT_SYMBOL(pci_pme_active); | 3011 | EXPORT_SYMBOL(pci_pme_active); |
| 2874 | EXPORT_SYMBOL(pci_enable_wake); | ||
| 2875 | EXPORT_SYMBOL(pci_wake_from_d3); | 3012 | EXPORT_SYMBOL(pci_wake_from_d3); |
| 2876 | EXPORT_SYMBOL(pci_target_state); | 3013 | EXPORT_SYMBOL(pci_target_state); |
| 2877 | EXPORT_SYMBOL(pci_prepare_to_sleep); | 3014 | EXPORT_SYMBOL(pci_prepare_to_sleep); |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index fbd0e3adbca3..4eb10f48d270 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
| @@ -35,6 +35,10 @@ int pci_probe_reset_function(struct pci_dev *dev); | |||
| 35 | * | 35 | * |
| 36 | * @sleep_wake: enables/disables the system wake up capability of given device | 36 | * @sleep_wake: enables/disables the system wake up capability of given device |
| 37 | * | 37 | * |
| 38 | * @run_wake: enables/disables the platform to generate run-time wake-up events | ||
| 39 | * for given device (the device's wake-up capability has to be | ||
| 40 | * enabled by @sleep_wake for this feature to work) | ||
| 41 | * | ||
| 38 | * If given platform is generally capable of power managing PCI devices, all of | 42 | * If given platform is generally capable of power managing PCI devices, all of |
| 39 | * these callbacks are mandatory. | 43 | * these callbacks are mandatory. |
| 40 | */ | 44 | */ |
| @@ -44,11 +48,16 @@ struct pci_platform_pm_ops { | |||
| 44 | pci_power_t (*choose_state)(struct pci_dev *dev); | 48 | pci_power_t (*choose_state)(struct pci_dev *dev); |
| 45 | bool (*can_wakeup)(struct pci_dev *dev); | 49 | bool (*can_wakeup)(struct pci_dev *dev); |
| 46 | int (*sleep_wake)(struct pci_dev *dev, bool enable); | 50 | int (*sleep_wake)(struct pci_dev *dev, bool enable); |
| 51 | int (*run_wake)(struct pci_dev *dev, bool enable); | ||
| 47 | }; | 52 | }; |
| 48 | 53 | ||
| 49 | extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops); | 54 | extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops); |
| 50 | extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state); | 55 | extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state); |
| 51 | extern void pci_disable_enabled_device(struct pci_dev *dev); | 56 | extern void pci_disable_enabled_device(struct pci_dev *dev); |
| 57 | extern bool pci_check_pme_status(struct pci_dev *dev); | ||
| 58 | extern int pci_finish_runtime_suspend(struct pci_dev *dev); | ||
| 59 | extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign); | ||
| 60 | extern void pci_pme_wakeup_bus(struct pci_bus *bus); | ||
| 52 | extern void pci_pm_init(struct pci_dev *dev); | 61 | extern void pci_pm_init(struct pci_dev *dev); |
| 53 | extern void platform_pci_wakeup_init(struct pci_dev *dev); | 62 | extern void platform_pci_wakeup_init(struct pci_dev *dev); |
| 54 | extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); | 63 | extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); |
| @@ -319,6 +328,13 @@ struct pci_dev_reset_methods { | |||
| 319 | int (*reset)(struct pci_dev *dev, int probe); | 328 | int (*reset)(struct pci_dev *dev, int probe); |
| 320 | }; | 329 | }; |
| 321 | 330 | ||
| 331 | #ifdef CONFIG_PCI_QUIRKS | ||
| 322 | extern int pci_dev_specific_reset(struct pci_dev *dev, int probe); | 332 | extern int pci_dev_specific_reset(struct pci_dev *dev, int probe); |
| 333 | #else | ||
| 334 | static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe) | ||
| 335 | { | ||
| 336 | return -ENOTTY; | ||
| 337 | } | ||
| 338 | #endif | ||
| 323 | 339 | ||
| 324 | #endif /* DRIVERS_PCI_H */ | 340 | #endif /* DRIVERS_PCI_H */ |
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index 5a0c6ad53f8e..b8b494b3e0d0 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig | |||
| @@ -46,3 +46,7 @@ config PCIEASPM_DEBUG | |||
| 46 | help | 46 | help |
| 47 | This enables PCI Express ASPM debug support. It will add per-device | 47 | This enables PCI Express ASPM debug support. It will add per-device |
| 48 | interface to control ASPM. | 48 | interface to control ASPM. |
| 49 | |||
| 50 | config PCIE_PME | ||
| 51 | def_bool y | ||
| 52 | depends on PCIEPORTBUS && PM_RUNTIME && EXPERIMENTAL && ACPI | ||
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile index 11f6bb1eae24..ea654545e7c4 100644 --- a/drivers/pci/pcie/Makefile +++ b/drivers/pci/pcie/Makefile | |||
| @@ -11,3 +11,5 @@ obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o | |||
| 11 | 11 | ||
| 12 | # Build PCI Express AER if needed | 12 | # Build PCI Express AER if needed |
| 13 | obj-$(CONFIG_PCIEAER) += aer/ | 13 | obj-$(CONFIG_PCIEAER) += aer/ |
| 14 | |||
| 15 | obj-$(CONFIG_PCIE_PME) += pme/ | ||
diff --git a/drivers/pci/pcie/pme/Makefile b/drivers/pci/pcie/pme/Makefile new file mode 100644 index 000000000000..8b9238053080 --- /dev/null +++ b/drivers/pci/pcie/pme/Makefile | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | # | ||
| 2 | # Makefile for PCI-Express Root Port PME signaling driver | ||
| 3 | # | ||
| 4 | |||
| 5 | obj-$(CONFIG_PCIE_PME) += pmedriver.o | ||
| 6 | |||
| 7 | pmedriver-objs := pcie_pme.o | ||
| 8 | pmedriver-$(CONFIG_ACPI) += pcie_pme_acpi.o | ||
diff --git a/drivers/pci/pcie/pme/pcie_pme.c b/drivers/pci/pcie/pme/pcie_pme.c new file mode 100644 index 000000000000..7b3cbff547ee --- /dev/null +++ b/drivers/pci/pcie/pme/pcie_pme.c | |||
| @@ -0,0 +1,505 @@ | |||
| 1 | /* | ||
| 2 | * PCIe Native PME support | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 - 2009 Intel Corp | ||
| 5 | * Copyright (C) 2007 - 2009 Shaohua Li <shaohua.li@intel.com> | ||
| 6 | * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
| 7 | * | ||
| 8 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 9 | * License V2. See the file "COPYING" in the main directory of this archive | ||
| 10 | * for more details. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/pci.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/errno.h> | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | #include <linux/device.h> | ||
| 20 | #include <linux/pcieport_if.h> | ||
| 21 | #include <linux/acpi.h> | ||
| 22 | #include <linux/pci-acpi.h> | ||
| 23 | #include <linux/pm_runtime.h> | ||
| 24 | |||
| 25 | #include "../../pci.h" | ||
| 26 | #include "pcie_pme.h" | ||
| 27 | |||
| 28 | #define PCI_EXP_RTSTA_PME 0x10000 /* PME status */ | ||
| 29 | #define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */ | ||
| 30 | |||
| 31 | /* | ||
| 32 | * If set, this switch will prevent the PCIe root port PME service driver from | ||
| 33 | * being registered. Consequently, the interrupt-based PCIe PME signaling will | ||
| 34 | * not be used by any PCIe root ports in that case. | ||
| 35 | */ | ||
| 36 | static bool pcie_pme_disabled; | ||
| 37 | |||
| 38 | /* | ||
| 39 | * The PCI Express Base Specification 2.0, Section 6.1.8, states the following: | ||
| 40 | * "In order to maintain compatibility with non-PCI Express-aware system | ||
| 41 | * software, system power management logic must be configured by firmware to use | ||
| 42 | * the legacy mechanism of signaling PME by default. PCI Express-aware system | ||
| 43 | * software must notify the firmware prior to enabling native, interrupt-based | ||
| 44 | * PME signaling." However, if the platform doesn't provide us with a suitable | ||
| 45 | * notification mechanism or the notification fails, it is not clear whether or | ||
| 46 | * not we are supposed to use the interrupt-based PCIe PME signaling. The | ||
| 47 | * switch below can be used to indicate the desired behaviour. When set, it | ||
| 48 | * will make the kernel use the interrupt-based PCIe PME signaling regardless of | ||
| 49 | * the platform notification status, although the kernel will attempt to notify | ||
| 50 | * the platform anyway. When unset, it will prevent the kernel from using the | ||
| 51 | * the interrupt-based PCIe PME signaling if the platform notification fails, | ||
| 52 | * which is the default. | ||
| 53 | */ | ||
| 54 | static bool pcie_pme_force_enable; | ||
| 55 | |||
| 56 | /* | ||
| 57 | * If this switch is set, MSI will not be used for PCIe PME signaling. This | ||
| 58 | * causes the PCIe port driver to use INTx interrupts only, but it turns out | ||
| 59 | * that using MSI for PCIe PME signaling doesn't play well with PCIe PME-based | ||
| 60 | * wake-up from system sleep states. | ||
| 61 | */ | ||
| 62 | bool pcie_pme_msi_disabled; | ||
| 63 | |||
| 64 | static int __init pcie_pme_setup(char *str) | ||
| 65 | { | ||
| 66 | if (!strcmp(str, "off")) | ||
| 67 | pcie_pme_disabled = true; | ||
| 68 | else if (!strcmp(str, "force")) | ||
| 69 | pcie_pme_force_enable = true; | ||
| 70 | else if (!strcmp(str, "nomsi")) | ||
| 71 | pcie_pme_msi_disabled = true; | ||
| 72 | return 1; | ||
| 73 | } | ||
| 74 | __setup("pcie_pme=", pcie_pme_setup); | ||
| 75 | |||
| 76 | /** | ||
| 77 | * pcie_pme_platform_setup - Ensure that the kernel controls the PCIe PME. | ||
| 78 | * @srv: PCIe PME root port service to use for carrying out the check. | ||
| 79 | * | ||
| 80 | * Notify the platform that the native PCIe PME is going to be used and return | ||
| 81 | * 'true' if the control of the PCIe PME registers has been acquired from the | ||
| 82 | * platform. | ||
| 83 | */ | ||
| 84 | static bool pcie_pme_platform_setup(struct pcie_device *srv) | ||
| 85 | { | ||
| 86 | if (!pcie_pme_platform_notify(srv)) | ||
| 87 | return true; | ||
| 88 | return pcie_pme_force_enable; | ||
| 89 | } | ||
| 90 | |||
| 91 | struct pcie_pme_service_data { | ||
| 92 | spinlock_t lock; | ||
| 93 | struct pcie_device *srv; | ||
| 94 | struct work_struct work; | ||
| 95 | bool noirq; /* Don't enable the PME interrupt used by this service. */ | ||
| 96 | }; | ||
| 97 | |||
| 98 | /** | ||
| 99 | * pcie_pme_interrupt_enable - Enable/disable PCIe PME interrupt generation. | ||
| 100 | * @dev: PCIe root port or event collector. | ||
| 101 | * @enable: Enable or disable the interrupt. | ||
| 102 | */ | ||
| 103 | static void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable) | ||
| 104 | { | ||
| 105 | int rtctl_pos; | ||
| 106 | u16 rtctl; | ||
| 107 | |||
| 108 | rtctl_pos = pci_pcie_cap(dev) + PCI_EXP_RTCTL; | ||
| 109 | |||
| 110 | pci_read_config_word(dev, rtctl_pos, &rtctl); | ||
| 111 | if (enable) | ||
| 112 | rtctl |= PCI_EXP_RTCTL_PMEIE; | ||
| 113 | else | ||
| 114 | rtctl &= ~PCI_EXP_RTCTL_PMEIE; | ||
| 115 | pci_write_config_word(dev, rtctl_pos, rtctl); | ||
| 116 | } | ||
| 117 | |||
| 118 | /** | ||
| 119 | * pcie_pme_clear_status - Clear root port PME interrupt status. | ||
| 120 | * @dev: PCIe root port or event collector. | ||
| 121 | */ | ||
| 122 | static void pcie_pme_clear_status(struct pci_dev *dev) | ||
| 123 | { | ||
| 124 | int rtsta_pos; | ||
| 125 | u32 rtsta; | ||
| 126 | |||
| 127 | rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA; | ||
| 128 | |||
| 129 | pci_read_config_dword(dev, rtsta_pos, &rtsta); | ||
| 130 | rtsta |= PCI_EXP_RTSTA_PME; | ||
| 131 | pci_write_config_dword(dev, rtsta_pos, rtsta); | ||
| 132 | } | ||
| 133 | |||
| 134 | /** | ||
| 135 | * pcie_pme_walk_bus - Scan a PCI bus for devices asserting PME#. | ||
| 136 | * @bus: PCI bus to scan. | ||
| 137 | * | ||
| 138 | * Scan given PCI bus and all buses under it for devices asserting PME#. | ||
| 139 | */ | ||
| 140 | static bool pcie_pme_walk_bus(struct pci_bus *bus) | ||
| 141 | { | ||
| 142 | struct pci_dev *dev; | ||
| 143 | bool ret = false; | ||
| 144 | |||
| 145 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
| 146 | /* Skip PCIe devices in case we started from a root port. */ | ||
| 147 | if (!pci_is_pcie(dev) && pci_check_pme_status(dev)) { | ||
| 148 | pm_request_resume(&dev->dev); | ||
| 149 | ret = true; | ||
| 150 | } | ||
| 151 | |||
| 152 | if (dev->subordinate && pcie_pme_walk_bus(dev->subordinate)) | ||
| 153 | ret = true; | ||
| 154 | } | ||
| 155 | |||
| 156 | return ret; | ||
| 157 | } | ||
| 158 | |||
| 159 | /** | ||
| 160 | * pcie_pme_from_pci_bridge - Check if PCIe-PCI bridge generated a PME. | ||
| 161 | * @bus: Secondary bus of the bridge. | ||
| 162 | * @devfn: Device/function number to check. | ||
| 163 | * | ||
| 164 | * PME from PCI devices under a PCIe-PCI bridge may be converted to an in-band | ||
| 165 | * PCIe PME message. In such that case the bridge should use the Requester ID | ||
| 166 | * of device/function number 0 on its secondary bus. | ||
| 167 | */ | ||
| 168 | static bool pcie_pme_from_pci_bridge(struct pci_bus *bus, u8 devfn) | ||
| 169 | { | ||
| 170 | struct pci_dev *dev; | ||
| 171 | bool found = false; | ||
| 172 | |||
| 173 | if (devfn) | ||
| 174 | return false; | ||
| 175 | |||
| 176 | dev = pci_dev_get(bus->self); | ||
| 177 | if (!dev) | ||
| 178 | return false; | ||
| 179 | |||
| 180 | if (pci_is_pcie(dev) && dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) { | ||
| 181 | down_read(&pci_bus_sem); | ||
| 182 | if (pcie_pme_walk_bus(bus)) | ||
| 183 | found = true; | ||
| 184 | up_read(&pci_bus_sem); | ||
| 185 | } | ||
| 186 | |||
| 187 | pci_dev_put(dev); | ||
| 188 | return found; | ||
| 189 | } | ||
| 190 | |||
| 191 | /** | ||
| 192 | * pcie_pme_handle_request - Find device that generated PME and handle it. | ||
| 193 | * @port: Root port or event collector that generated the PME interrupt. | ||
| 194 | * @req_id: PCIe Requester ID of the device that generated the PME. | ||
| 195 | */ | ||
| 196 | static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id) | ||
| 197 | { | ||
| 198 | u8 busnr = req_id >> 8, devfn = req_id & 0xff; | ||
| 199 | struct pci_bus *bus; | ||
| 200 | struct pci_dev *dev; | ||
| 201 | bool found = false; | ||
| 202 | |||
| 203 | /* First, check if the PME is from the root port itself. */ | ||
| 204 | if (port->devfn == devfn && port->bus->number == busnr) { | ||
| 205 | if (pci_check_pme_status(port)) { | ||
| 206 | pm_request_resume(&port->dev); | ||
| 207 | found = true; | ||
| 208 | } else { | ||
| 209 | /* | ||
| 210 | * Apparently, the root port generated the PME on behalf | ||
| 211 | * of a non-PCIe device downstream. If this is done by | ||
| 212 | * a root port, the Requester ID field in its status | ||
| 213 | * register may contain either the root port's, or the | ||
| 214 | * source device's information (PCI Express Base | ||
| 215 | * Specification, Rev. 2.0, Section 6.1.9). | ||
| 216 | */ | ||
| 217 | down_read(&pci_bus_sem); | ||
| 218 | found = pcie_pme_walk_bus(port->subordinate); | ||
| 219 | up_read(&pci_bus_sem); | ||
| 220 | } | ||
| 221 | goto out; | ||
| 222 | } | ||
| 223 | |||
| 224 | /* Second, find the bus the source device is on. */ | ||
| 225 | bus = pci_find_bus(pci_domain_nr(port->bus), busnr); | ||
| 226 | if (!bus) | ||
| 227 | goto out; | ||
| 228 | |||
| 229 | /* Next, check if the PME is from a PCIe-PCI bridge. */ | ||
| 230 | found = pcie_pme_from_pci_bridge(bus, devfn); | ||
| 231 | if (found) | ||
| 232 | goto out; | ||
| 233 | |||
| 234 | /* Finally, try to find the PME source on the bus. */ | ||
| 235 | down_read(&pci_bus_sem); | ||
| 236 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
| 237 | pci_dev_get(dev); | ||
| 238 | if (dev->devfn == devfn) { | ||
| 239 | found = true; | ||
| 240 | break; | ||
| 241 | } | ||
| 242 | pci_dev_put(dev); | ||
| 243 | } | ||
| 244 | up_read(&pci_bus_sem); | ||
| 245 | |||
| 246 | if (found) { | ||
| 247 | /* The device is there, but we have to check its PME status. */ | ||
| 248 | found = pci_check_pme_status(dev); | ||
| 249 | if (found) | ||
| 250 | pm_request_resume(&dev->dev); | ||
| 251 | pci_dev_put(dev); | ||
| 252 | } else if (devfn) { | ||
| 253 | /* | ||
| 254 | * The device is not there, but we can still try to recover by | ||
| 255 | * assuming that the PME was reported by a PCIe-PCI bridge that | ||
| 256 | * used devfn different from zero. | ||
| 257 | */ | ||
| 258 | dev_dbg(&port->dev, "PME interrupt generated for " | ||
| 259 | "non-existent device %02x:%02x.%d\n", | ||
| 260 | busnr, PCI_SLOT(devfn), PCI_FUNC(devfn)); | ||
| 261 | found = pcie_pme_from_pci_bridge(bus, 0); | ||
| 262 | } | ||
| 263 | |||
| 264 | out: | ||
| 265 | if (!found) | ||
| 266 | dev_dbg(&port->dev, "Spurious native PME interrupt!\n"); | ||
| 267 | } | ||
| 268 | |||
| 269 | /** | ||
| 270 | * pcie_pme_work_fn - Work handler for PCIe PME interrupt. | ||
| 271 | * @work: Work structure giving access to service data. | ||
| 272 | */ | ||
| 273 | static void pcie_pme_work_fn(struct work_struct *work) | ||
| 274 | { | ||
| 275 | struct pcie_pme_service_data *data = | ||
| 276 | container_of(work, struct pcie_pme_service_data, work); | ||
| 277 | struct pci_dev *port = data->srv->port; | ||
| 278 | int rtsta_pos; | ||
| 279 | u32 rtsta; | ||
| 280 | |||
| 281 | rtsta_pos = pci_pcie_cap(port) + PCI_EXP_RTSTA; | ||
| 282 | |||
| 283 | spin_lock_irq(&data->lock); | ||
| 284 | |||
| 285 | for (;;) { | ||
| 286 | if (data->noirq) | ||
| 287 | break; | ||
| 288 | |||
| 289 | pci_read_config_dword(port, rtsta_pos, &rtsta); | ||
| 290 | if (rtsta & PCI_EXP_RTSTA_PME) { | ||
| 291 | /* | ||
| 292 | * Clear PME status of the port. If there are other | ||
| 293 | * pending PMEs, the status will be set again. | ||
| 294 | */ | ||
| 295 | pcie_pme_clear_status(port); | ||
| 296 | |||
| 297 | spin_unlock_irq(&data->lock); | ||
| 298 | pcie_pme_handle_request(port, rtsta & 0xffff); | ||
| 299 | spin_lock_irq(&data->lock); | ||
| 300 | |||
| 301 | continue; | ||
| 302 | } | ||
| 303 | |||
| 304 | /* No need to loop if there are no more PMEs pending. */ | ||
| 305 | if (!(rtsta & PCI_EXP_RTSTA_PENDING)) | ||
| 306 | break; | ||
| 307 | |||
| 308 | spin_unlock_irq(&data->lock); | ||
| 309 | cpu_relax(); | ||
| 310 | spin_lock_irq(&data->lock); | ||
| 311 | } | ||
| 312 | |||
| 313 | if (!data->noirq) | ||
| 314 | pcie_pme_interrupt_enable(port, true); | ||
| 315 | |||
| 316 | spin_unlock_irq(&data->lock); | ||
| 317 | } | ||
| 318 | |||
| 319 | /** | ||
| 320 | * pcie_pme_irq - Interrupt handler for PCIe root port PME interrupt. | ||
| 321 | * @irq: Interrupt vector. | ||
| 322 | * @context: Interrupt context pointer. | ||
| 323 | */ | ||
| 324 | static irqreturn_t pcie_pme_irq(int irq, void *context) | ||
| 325 | { | ||
| 326 | struct pci_dev *port; | ||
| 327 | struct pcie_pme_service_data *data; | ||
| 328 | int rtsta_pos; | ||
| 329 | u32 rtsta; | ||
| 330 | unsigned long flags; | ||
| 331 | |||
| 332 | port = ((struct pcie_device *)context)->port; | ||
| 333 | data = get_service_data((struct pcie_device *)context); | ||
| 334 | |||
| 335 | rtsta_pos = pci_pcie_cap(port) + PCI_EXP_RTSTA; | ||
| 336 | |||
| 337 | spin_lock_irqsave(&data->lock, flags); | ||
| 338 | pci_read_config_dword(port, rtsta_pos, &rtsta); | ||
| 339 | |||
| 340 | if (!(rtsta & PCI_EXP_RTSTA_PME)) { | ||
| 341 | spin_unlock_irqrestore(&data->lock, flags); | ||
| 342 | return IRQ_NONE; | ||
| 343 | } | ||
| 344 | |||
| 345 | pcie_pme_interrupt_enable(port, false); | ||
| 346 | spin_unlock_irqrestore(&data->lock, flags); | ||
| 347 | |||
| 348 | /* We don't use pm_wq, because it's freezable. */ | ||
| 349 | schedule_work(&data->work); | ||
| 350 | |||
| 351 | return IRQ_HANDLED; | ||
| 352 | } | ||
| 353 | |||
| 354 | /** | ||
| 355 | * pcie_pme_set_native - Set the PME interrupt flag for given device. | ||
| 356 | * @dev: PCI device to handle. | ||
| 357 | * @ign: Ignored. | ||
| 358 | */ | ||
| 359 | static int pcie_pme_set_native(struct pci_dev *dev, void *ign) | ||
| 360 | { | ||
| 361 | dev_info(&dev->dev, "Signaling PME through PCIe PME interrupt\n"); | ||
| 362 | |||
| 363 | device_set_run_wake(&dev->dev, true); | ||
| 364 | dev->pme_interrupt = true; | ||
| 365 | return 0; | ||
| 366 | } | ||
| 367 | |||
| 368 | /** | ||
| 369 | * pcie_pme_mark_devices - Set the PME interrupt flag for devices below a port. | ||
| 370 | * @port: PCIe root port or event collector to handle. | ||
| 371 | * | ||
| 372 | * For each device below given root port, including the port itself (or for each | ||
| 373 | * root complex integrated endpoint if @port is a root complex event collector) | ||
| 374 | * set the flag indicating that it can signal run-time wake-up events via PCIe | ||
| 375 | * PME interrupts. | ||
| 376 | */ | ||
| 377 | static void pcie_pme_mark_devices(struct pci_dev *port) | ||
| 378 | { | ||
| 379 | pcie_pme_set_native(port, NULL); | ||
| 380 | if (port->subordinate) { | ||
| 381 | pci_walk_bus(port->subordinate, pcie_pme_set_native, NULL); | ||
| 382 | } else { | ||
| 383 | struct pci_bus *bus = port->bus; | ||
| 384 | struct pci_dev *dev; | ||
| 385 | |||
| 386 | /* Check if this is a root port event collector. */ | ||
| 387 | if (port->pcie_type != PCI_EXP_TYPE_RC_EC || !bus) | ||
| 388 | return; | ||
| 389 | |||
| 390 | down_read(&pci_bus_sem); | ||
| 391 | list_for_each_entry(dev, &bus->devices, bus_list) | ||
| 392 | if (pci_is_pcie(dev) | ||
| 393 | && dev->pcie_type == PCI_EXP_TYPE_RC_END) | ||
| 394 | pcie_pme_set_native(dev, NULL); | ||
| 395 | up_read(&pci_bus_sem); | ||
| 396 | } | ||
| 397 | } | ||
| 398 | |||
| 399 | /** | ||
| 400 | * pcie_pme_probe - Initialize PCIe PME service for given root port. | ||
| 401 | * @srv: PCIe service to initialize. | ||
| 402 | */ | ||
| 403 | static int pcie_pme_probe(struct pcie_device *srv) | ||
| 404 | { | ||
| 405 | struct pci_dev *port; | ||
| 406 | struct pcie_pme_service_data *data; | ||
| 407 | int ret; | ||
| 408 | |||
| 409 | if (!pcie_pme_platform_setup(srv)) | ||
| 410 | return -EACCES; | ||
| 411 | |||
| 412 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
| 413 | if (!data) | ||
| 414 | return -ENOMEM; | ||
| 415 | |||
| 416 | spin_lock_init(&data->lock); | ||
| 417 | INIT_WORK(&data->work, pcie_pme_work_fn); | ||
| 418 | data->srv = srv; | ||
| 419 | set_service_data(srv, data); | ||
| 420 | |||
| 421 | port = srv->port; | ||
| 422 | pcie_pme_interrupt_enable(port, false); | ||
| 423 | pcie_pme_clear_status(port); | ||
| 424 | |||
| 425 | ret = request_irq(srv->irq, pcie_pme_irq, IRQF_SHARED, "PCIe PME", srv); | ||
| 426 | if (ret) { | ||
| 427 | kfree(data); | ||
| 428 | } else { | ||
| 429 | pcie_pme_mark_devices(port); | ||
| 430 | pcie_pme_interrupt_enable(port, true); | ||
| 431 | } | ||
| 432 | |||
| 433 | return ret; | ||
| 434 | } | ||
| 435 | |||
| 436 | /** | ||
| 437 | * pcie_pme_suspend - Suspend PCIe PME service device. | ||
| 438 | * @srv: PCIe service device to suspend. | ||
| 439 | */ | ||
| 440 | static int pcie_pme_suspend(struct pcie_device *srv) | ||
| 441 | { | ||
| 442 | struct pcie_pme_service_data *data = get_service_data(srv); | ||
| 443 | struct pci_dev *port = srv->port; | ||
| 444 | |||
| 445 | spin_lock_irq(&data->lock); | ||
| 446 | pcie_pme_interrupt_enable(port, false); | ||
| 447 | pcie_pme_clear_status(port); | ||
| 448 | data->noirq = true; | ||
| 449 | spin_unlock_irq(&data->lock); | ||
| 450 | |||
| 451 | synchronize_irq(srv->irq); | ||
| 452 | |||
| 453 | return 0; | ||
| 454 | } | ||
| 455 | |||
| 456 | /** | ||
| 457 | * pcie_pme_resume - Resume PCIe PME service device. | ||
| 458 | * @srv - PCIe service device to resume. | ||
| 459 | */ | ||
| 460 | static int pcie_pme_resume(struct pcie_device *srv) | ||
| 461 | { | ||
| 462 | struct pcie_pme_service_data *data = get_service_data(srv); | ||
| 463 | struct pci_dev *port = srv->port; | ||
| 464 | |||
| 465 | spin_lock_irq(&data->lock); | ||
| 466 | data->noirq = false; | ||
| 467 | pcie_pme_clear_status(port); | ||
| 468 | pcie_pme_interrupt_enable(port, true); | ||
| 469 | spin_unlock_irq(&data->lock); | ||
| 470 | |||
| 471 | return 0; | ||
| 472 | } | ||
| 473 | |||
| 474 | /** | ||
| 475 | * pcie_pme_remove - Prepare PCIe PME service device for removal. | ||
| 476 | * @srv - PCIe service device to resume. | ||
| 477 | */ | ||
| 478 | static void pcie_pme_remove(struct pcie_device *srv) | ||
| 479 | { | ||
| 480 | pcie_pme_suspend(srv); | ||
| 481 | free_irq(srv->irq, srv); | ||
| 482 | kfree(get_service_data(srv)); | ||
| 483 | } | ||
| 484 | |||
| 485 | static struct pcie_port_service_driver pcie_pme_driver = { | ||
| 486 | .name = "pcie_pme", | ||
| 487 | .port_type = PCI_EXP_TYPE_ROOT_PORT, | ||
| 488 | .service = PCIE_PORT_SERVICE_PME, | ||
| 489 | |||
| 490 | .probe = pcie_pme_probe, | ||
| 491 | .suspend = pcie_pme_suspend, | ||
| 492 | .resume = pcie_pme_resume, | ||
| 493 | .remove = pcie_pme_remove, | ||
| 494 | }; | ||
| 495 | |||
| 496 | /** | ||
| 497 | * pcie_pme_service_init - Register the PCIe PME service driver. | ||
| 498 | */ | ||
| 499 | static int __init pcie_pme_service_init(void) | ||
| 500 | { | ||
| 501 | return pcie_pme_disabled ? | ||
| 502 | -ENODEV : pcie_port_service_register(&pcie_pme_driver); | ||
| 503 | } | ||
| 504 | |||
| 505 | module_init(pcie_pme_service_init); | ||
diff --git a/drivers/pci/pcie/pme/pcie_pme.h b/drivers/pci/pcie/pme/pcie_pme.h new file mode 100644 index 000000000000..b30d2b7c9775 --- /dev/null +++ b/drivers/pci/pcie/pme/pcie_pme.h | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | /* | ||
| 2 | * drivers/pci/pcie/pme/pcie_pme.h | ||
| 3 | * | ||
| 4 | * PCI Express Root Port PME signaling support | ||
| 5 | * | ||
| 6 | * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef _PCIE_PME_H_ | ||
| 10 | #define _PCIE_PME_H_ | ||
| 11 | |||
| 12 | struct pcie_device; | ||
| 13 | |||
| 14 | #ifdef CONFIG_ACPI | ||
| 15 | extern int pcie_pme_acpi_setup(struct pcie_device *srv); | ||
| 16 | |||
| 17 | static inline int pcie_pme_platform_notify(struct pcie_device *srv) | ||
| 18 | { | ||
| 19 | return pcie_pme_acpi_setup(srv); | ||
| 20 | } | ||
| 21 | #else /* !CONFIG_ACPI */ | ||
| 22 | static inline int pcie_pme_platform_notify(struct pcie_device *srv) | ||
| 23 | { | ||
| 24 | return 0; | ||
| 25 | } | ||
| 26 | #endif /* !CONFIG_ACPI */ | ||
| 27 | |||
| 28 | #endif | ||
diff --git a/drivers/pci/pcie/pme/pcie_pme_acpi.c b/drivers/pci/pcie/pme/pcie_pme_acpi.c new file mode 100644 index 000000000000..83ab2287ae3f --- /dev/null +++ b/drivers/pci/pcie/pme/pcie_pme_acpi.c | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | /* | ||
| 2 | * PCIe Native PME support, ACPI-related part | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
| 5 | * | ||
| 6 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 7 | * License V2. See the file "COPYING" in the main directory of this archive | ||
| 8 | * for more details. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/pci.h> | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/errno.h> | ||
| 14 | #include <linux/acpi.h> | ||
| 15 | #include <linux/pci-acpi.h> | ||
| 16 | #include <linux/pcieport_if.h> | ||
| 17 | |||
| 18 | /** | ||
| 19 | * pcie_pme_acpi_setup - Request the ACPI BIOS to release control over PCIe PME. | ||
| 20 | * @srv - PCIe PME service for a root port or event collector. | ||
| 21 | * | ||
| 22 | * Invoked when the PCIe bus type loads PCIe PME service driver. To avoid | ||
| 23 | * conflict with the BIOS PCIe support requires the BIOS to yield PCIe PME | ||
| 24 | * control to the kernel. | ||
| 25 | */ | ||
| 26 | int pcie_pme_acpi_setup(struct pcie_device *srv) | ||
| 27 | { | ||
| 28 | acpi_status status = AE_NOT_FOUND; | ||
| 29 | struct pci_dev *port = srv->port; | ||
| 30 | acpi_handle handle; | ||
| 31 | int error = 0; | ||
| 32 | |||
| 33 | if (acpi_pci_disabled) | ||
| 34 | return -ENOSYS; | ||
| 35 | |||
| 36 | dev_info(&port->dev, "Requesting control of PCIe PME from ACPI BIOS\n"); | ||
| 37 | |||
| 38 | handle = acpi_find_root_bridge_handle(port); | ||
| 39 | if (!handle) | ||
| 40 | return -EINVAL; | ||
| 41 | |||
| 42 | status = acpi_pci_osc_control_set(handle, | ||
| 43 | OSC_PCI_EXPRESS_PME_CONTROL | | ||
| 44 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | ||
| 45 | if (ACPI_FAILURE(status)) { | ||
| 46 | dev_info(&port->dev, | ||
| 47 | "Failed to receive control of PCIe PME service: %s\n", | ||
| 48 | (status == AE_SUPPORT || status == AE_NOT_FOUND) ? | ||
| 49 | "no _OSC support" : "ACPI _OSC failed"); | ||
| 50 | error = -ENODEV; | ||
| 51 | } | ||
| 52 | |||
| 53 | return error; | ||
| 54 | } | ||
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index aaeb9d21cba5..813a5c3427b6 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h | |||
| @@ -30,4 +30,21 @@ extern void pcie_port_device_remove(struct pci_dev *dev); | |||
| 30 | extern int __must_check pcie_port_bus_register(void); | 30 | extern int __must_check pcie_port_bus_register(void); |
| 31 | extern void pcie_port_bus_unregister(void); | 31 | extern void pcie_port_bus_unregister(void); |
| 32 | 32 | ||
| 33 | #ifdef CONFIG_PCIE_PME | ||
| 34 | extern bool pcie_pme_msi_disabled; | ||
| 35 | |||
| 36 | static inline void pcie_pme_disable_msi(void) | ||
| 37 | { | ||
| 38 | pcie_pme_msi_disabled = true; | ||
| 39 | } | ||
| 40 | |||
| 41 | static inline bool pcie_pme_no_msi(void) | ||
| 42 | { | ||
| 43 | return pcie_pme_msi_disabled; | ||
| 44 | } | ||
| 45 | #else /* !CONFIG_PCIE_PME */ | ||
| 46 | static inline void pcie_pme_disable_msi(void) {} | ||
| 47 | static inline bool pcie_pme_no_msi(void) { return false; } | ||
| 48 | #endif /* !CONFIG_PCIE_PME */ | ||
| 49 | |||
| 33 | #endif /* _PORTDRV_H_ */ | 50 | #endif /* _PORTDRV_H_ */ |
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index b174188ac121..0d34ff415399 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c | |||
| @@ -186,16 +186,24 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask) | |||
| 186 | */ | 186 | */ |
| 187 | static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask) | 187 | static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask) |
| 188 | { | 188 | { |
| 189 | int i, irq; | 189 | int i, irq = -1; |
| 190 | |||
| 191 | /* We have to use INTx if MSI cannot be used for PCIe PME. */ | ||
| 192 | if ((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi()) { | ||
| 193 | if (dev->pin) | ||
| 194 | irq = dev->irq; | ||
| 195 | goto no_msi; | ||
| 196 | } | ||
| 190 | 197 | ||
| 191 | /* Try to use MSI-X if supported */ | 198 | /* Try to use MSI-X if supported */ |
| 192 | if (!pcie_port_enable_msix(dev, irqs, mask)) | 199 | if (!pcie_port_enable_msix(dev, irqs, mask)) |
| 193 | return 0; | 200 | return 0; |
| 201 | |||
| 194 | /* We're not going to use MSI-X, so try MSI and fall back to INTx */ | 202 | /* We're not going to use MSI-X, so try MSI and fall back to INTx */ |
| 195 | irq = -1; | ||
| 196 | if (!pci_enable_msi(dev) || dev->pin) | 203 | if (!pci_enable_msi(dev) || dev->pin) |
| 197 | irq = dev->irq; | 204 | irq = dev->irq; |
| 198 | 205 | ||
| 206 | no_msi: | ||
| 199 | for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) | 207 | for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) |
| 200 | irqs[i] = irq; | 208 | irqs[i] = irq; |
| 201 | irqs[PCIE_PORT_SERVICE_VC_SHIFT] = -1; | 209 | irqs[PCIE_PORT_SERVICE_VC_SHIFT] = -1; |
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 13c8972886e6..127e8f169d9c 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/pcieport_if.h> | 16 | #include <linux/pcieport_if.h> |
| 17 | #include <linux/aer.h> | 17 | #include <linux/aer.h> |
| 18 | #include <linux/dmi.h> | ||
| 18 | 19 | ||
| 19 | #include "portdrv.h" | 20 | #include "portdrv.h" |
| 20 | #include "aer/aerdrv.h" | 21 | #include "aer/aerdrv.h" |
| @@ -273,10 +274,36 @@ static struct pci_driver pcie_portdriver = { | |||
| 273 | .driver.pm = PCIE_PORTDRV_PM_OPS, | 274 | .driver.pm = PCIE_PORTDRV_PM_OPS, |
| 274 | }; | 275 | }; |
| 275 | 276 | ||
| 277 | static int __init dmi_pcie_pme_disable_msi(const struct dmi_system_id *d) | ||
| 278 | { | ||
| 279 | pr_notice("%s detected: will not use MSI for PCIe PME signaling\n", | ||
| 280 | d->ident); | ||
| 281 | pcie_pme_disable_msi(); | ||
| 282 | return 0; | ||
| 283 | } | ||
| 284 | |||
| 285 | static struct dmi_system_id __initdata pcie_portdrv_dmi_table[] = { | ||
| 286 | /* | ||
| 287 | * Boxes that should not use MSI for PCIe PME signaling. | ||
| 288 | */ | ||
| 289 | { | ||
| 290 | .callback = dmi_pcie_pme_disable_msi, | ||
| 291 | .ident = "MSI Wind U-100", | ||
| 292 | .matches = { | ||
| 293 | DMI_MATCH(DMI_SYS_VENDOR, | ||
| 294 | "MICRO-STAR INTERNATIONAL CO., LTD"), | ||
| 295 | DMI_MATCH(DMI_PRODUCT_NAME, "U-100"), | ||
| 296 | }, | ||
| 297 | }, | ||
| 298 | {} | ||
| 299 | }; | ||
| 300 | |||
| 276 | static int __init pcie_portdrv_init(void) | 301 | static int __init pcie_portdrv_init(void) |
| 277 | { | 302 | { |
| 278 | int retval; | 303 | int retval; |
| 279 | 304 | ||
| 305 | dmi_check_system(pcie_portdrv_dmi_table); | ||
| 306 | |||
| 280 | retval = pcie_port_bus_register(); | 307 | retval = pcie_port_bus_register(); |
| 281 | if (retval) { | 308 | if (retval) { |
| 282 | printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval); | 309 | printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval); |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 446e4a94d7d3..270d069819f7 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
| @@ -89,6 +89,7 @@ static void release_pcibus_dev(struct device *dev) | |||
| 89 | 89 | ||
| 90 | if (pci_bus->bridge) | 90 | if (pci_bus->bridge) |
| 91 | put_device(pci_bus->bridge); | 91 | put_device(pci_bus->bridge); |
| 92 | pci_bus_remove_resources(pci_bus); | ||
| 92 | kfree(pci_bus); | 93 | kfree(pci_bus); |
| 93 | } | 94 | } |
| 94 | 95 | ||
| @@ -281,26 +282,12 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) | |||
| 281 | } | 282 | } |
| 282 | } | 283 | } |
| 283 | 284 | ||
| 284 | void __devinit pci_read_bridge_bases(struct pci_bus *child) | 285 | static void __devinit pci_read_bridge_io(struct pci_bus *child) |
| 285 | { | 286 | { |
| 286 | struct pci_dev *dev = child->self; | 287 | struct pci_dev *dev = child->self; |
| 287 | u8 io_base_lo, io_limit_lo; | 288 | u8 io_base_lo, io_limit_lo; |
| 288 | u16 mem_base_lo, mem_limit_lo; | ||
| 289 | unsigned long base, limit; | 289 | unsigned long base, limit; |
| 290 | struct resource *res; | 290 | struct resource *res; |
| 291 | int i; | ||
| 292 | |||
| 293 | if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */ | ||
| 294 | return; | ||
| 295 | |||
| 296 | dev_info(&dev->dev, "PCI bridge to [bus %02x-%02x]%s\n", | ||
| 297 | child->secondary, child->subordinate, | ||
| 298 | dev->transparent ? " (subtractive decode)": ""); | ||
| 299 | |||
| 300 | if (dev->transparent) { | ||
| 301 | for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++) | ||
| 302 | child->resource[i] = child->parent->resource[i - 3]; | ||
| 303 | } | ||
| 304 | 291 | ||
| 305 | res = child->resource[0]; | 292 | res = child->resource[0]; |
| 306 | pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); | 293 | pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); |
| @@ -316,26 +303,50 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) | |||
| 316 | limit |= (io_limit_hi << 16); | 303 | limit |= (io_limit_hi << 16); |
| 317 | } | 304 | } |
| 318 | 305 | ||
| 319 | if (base <= limit) { | 306 | if (base && base <= limit) { |
| 320 | res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO; | 307 | res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO; |
| 321 | if (!res->start) | 308 | if (!res->start) |
| 322 | res->start = base; | 309 | res->start = base; |
| 323 | if (!res->end) | 310 | if (!res->end) |
| 324 | res->end = limit + 0xfff; | 311 | res->end = limit + 0xfff; |
| 325 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); | 312 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); |
| 313 | } else { | ||
| 314 | dev_printk(KERN_DEBUG, &dev->dev, | ||
| 315 | " bridge window [io %04lx - %04lx] reg reading\n", | ||
| 316 | base, limit); | ||
| 326 | } | 317 | } |
| 318 | } | ||
| 319 | |||
| 320 | static void __devinit pci_read_bridge_mmio(struct pci_bus *child) | ||
| 321 | { | ||
| 322 | struct pci_dev *dev = child->self; | ||
| 323 | u16 mem_base_lo, mem_limit_lo; | ||
| 324 | unsigned long base, limit; | ||
| 325 | struct resource *res; | ||
| 327 | 326 | ||
| 328 | res = child->resource[1]; | 327 | res = child->resource[1]; |
| 329 | pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo); | 328 | pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo); |
| 330 | pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo); | 329 | pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo); |
| 331 | base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16; | 330 | base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16; |
| 332 | limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16; | 331 | limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16; |
| 333 | if (base <= limit) { | 332 | if (base && base <= limit) { |
| 334 | res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM; | 333 | res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM; |
| 335 | res->start = base; | 334 | res->start = base; |
| 336 | res->end = limit + 0xfffff; | 335 | res->end = limit + 0xfffff; |
| 337 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); | 336 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); |
| 337 | } else { | ||
| 338 | dev_printk(KERN_DEBUG, &dev->dev, | ||
| 339 | " bridge window [mem 0x%08lx - 0x%08lx] reg reading\n", | ||
| 340 | base, limit + 0xfffff); | ||
| 338 | } | 341 | } |
| 342 | } | ||
| 343 | |||
| 344 | static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child) | ||
| 345 | { | ||
| 346 | struct pci_dev *dev = child->self; | ||
| 347 | u16 mem_base_lo, mem_limit_lo; | ||
| 348 | unsigned long base, limit; | ||
| 349 | struct resource *res; | ||
| 339 | 350 | ||
| 340 | res = child->resource[2]; | 351 | res = child->resource[2]; |
| 341 | pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); | 352 | pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); |
| @@ -366,7 +377,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) | |||
| 366 | #endif | 377 | #endif |
| 367 | } | 378 | } |
| 368 | } | 379 | } |
| 369 | if (base <= limit) { | 380 | if (base && base <= limit) { |
| 370 | res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) | | 381 | res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) | |
| 371 | IORESOURCE_MEM | IORESOURCE_PREFETCH; | 382 | IORESOURCE_MEM | IORESOURCE_PREFETCH; |
| 372 | if (res->flags & PCI_PREF_RANGE_TYPE_64) | 383 | if (res->flags & PCI_PREF_RANGE_TYPE_64) |
| @@ -374,6 +385,44 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) | |||
| 374 | res->start = base; | 385 | res->start = base; |
| 375 | res->end = limit + 0xfffff; | 386 | res->end = limit + 0xfffff; |
| 376 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); | 387 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); |
| 388 | } else { | ||
| 389 | dev_printk(KERN_DEBUG, &dev->dev, | ||
| 390 | " bridge window [mem 0x%08lx - %08lx pref] reg reading\n", | ||
| 391 | base, limit + 0xfffff); | ||
| 392 | } | ||
| 393 | } | ||
| 394 | |||
| 395 | void __devinit pci_read_bridge_bases(struct pci_bus *child) | ||
| 396 | { | ||
| 397 | struct pci_dev *dev = child->self; | ||
| 398 | struct resource *res; | ||
| 399 | int i; | ||
| 400 | |||
| 401 | if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */ | ||
| 402 | return; | ||
| 403 | |||
| 404 | dev_info(&dev->dev, "PCI bridge to [bus %02x-%02x]%s\n", | ||
| 405 | child->secondary, child->subordinate, | ||
| 406 | dev->transparent ? " (subtractive decode)" : ""); | ||
| 407 | |||
| 408 | pci_bus_remove_resources(child); | ||
| 409 | for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) | ||
| 410 | child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i]; | ||
| 411 | |||
| 412 | pci_read_bridge_io(child); | ||
| 413 | pci_read_bridge_mmio(child); | ||
| 414 | pci_read_bridge_mmio_pref(child); | ||
| 415 | |||
| 416 | if (dev->transparent) { | ||
| 417 | pci_bus_for_each_resource(child->parent, res, i) { | ||
| 418 | if (res) { | ||
| 419 | pci_bus_add_resource(child, res, | ||
| 420 | PCI_SUBTRACTIVE_DECODE); | ||
| 421 | dev_printk(KERN_DEBUG, &dev->dev, | ||
| 422 | " bridge window %pR (subtractive decode)\n", | ||
| 423 | res); | ||
| 424 | } | ||
| 425 | } | ||
| 377 | } | 426 | } |
| 378 | } | 427 | } |
| 379 | 428 | ||
| @@ -387,10 +436,147 @@ static struct pci_bus * pci_alloc_bus(void) | |||
| 387 | INIT_LIST_HEAD(&b->children); | 436 | INIT_LIST_HEAD(&b->children); |
| 388 | INIT_LIST_HEAD(&b->devices); | 437 | INIT_LIST_HEAD(&b->devices); |
| 389 | INIT_LIST_HEAD(&b->slots); | 438 | INIT_LIST_HEAD(&b->slots); |
| 439 | INIT_LIST_HEAD(&b->resources); | ||
| 440 | b->max_bus_speed = PCI_SPEED_UNKNOWN; | ||
| 441 | b->cur_bus_speed = PCI_SPEED_UNKNOWN; | ||
| 390 | } | 442 | } |
| 391 | return b; | 443 | return b; |
| 392 | } | 444 | } |
| 393 | 445 | ||
| 446 | static unsigned char pcix_bus_speed[] = { | ||
| 447 | PCI_SPEED_UNKNOWN, /* 0 */ | ||
| 448 | PCI_SPEED_66MHz_PCIX, /* 1 */ | ||
| 449 | PCI_SPEED_100MHz_PCIX, /* 2 */ | ||
| 450 | PCI_SPEED_133MHz_PCIX, /* 3 */ | ||
| 451 | PCI_SPEED_UNKNOWN, /* 4 */ | ||
| 452 | PCI_SPEED_66MHz_PCIX_ECC, /* 5 */ | ||
| 453 | PCI_SPEED_100MHz_PCIX_ECC, /* 6 */ | ||
| 454 | PCI_SPEED_133MHz_PCIX_ECC, /* 7 */ | ||
| 455 | PCI_SPEED_UNKNOWN, /* 8 */ | ||
| 456 | PCI_SPEED_66MHz_PCIX_266, /* 9 */ | ||
| 457 | PCI_SPEED_100MHz_PCIX_266, /* A */ | ||
| 458 | PCI_SPEED_133MHz_PCIX_266, /* B */ | ||
| 459 | PCI_SPEED_UNKNOWN, /* C */ | ||
| 460 | PCI_SPEED_66MHz_PCIX_533, /* D */ | ||
| 461 | PCI_SPEED_100MHz_PCIX_533, /* E */ | ||
| 462 | PCI_SPEED_133MHz_PCIX_533 /* F */ | ||
| 463 | }; | ||
| 464 | |||
| 465 | static unsigned char pcie_link_speed[] = { | ||
| 466 | PCI_SPEED_UNKNOWN, /* 0 */ | ||
| 467 | PCIE_SPEED_2_5GT, /* 1 */ | ||
| 468 | PCIE_SPEED_5_0GT, /* 2 */ | ||
| 469 | PCIE_SPEED_8_0GT, /* 3 */ | ||
| 470 | PCI_SPEED_UNKNOWN, /* 4 */ | ||
| 471 | PCI_SPEED_UNKNOWN, /* 5 */ | ||
| 472 | PCI_SPEED_UNKNOWN, /* 6 */ | ||
| 473 | PCI_SPEED_UNKNOWN, /* 7 */ | ||
| 474 | PCI_SPEED_UNKNOWN, /* 8 */ | ||
| 475 | PCI_SPEED_UNKNOWN, /* 9 */ | ||
| 476 | PCI_SPEED_UNKNOWN, /* A */ | ||
| 477 | PCI_SPEED_UNKNOWN, /* B */ | ||
| 478 | PCI_SPEED_UNKNOWN, /* C */ | ||
| 479 | PCI_SPEED_UNKNOWN, /* D */ | ||
| 480 | PCI_SPEED_UNKNOWN, /* E */ | ||
| 481 | PCI_SPEED_UNKNOWN /* F */ | ||
| 482 | }; | ||
| 483 | |||
| 484 | void pcie_update_link_speed(struct pci_bus *bus, u16 linksta) | ||
| 485 | { | ||
| 486 | bus->cur_bus_speed = pcie_link_speed[linksta & 0xf]; | ||
| 487 | } | ||
| 488 | EXPORT_SYMBOL_GPL(pcie_update_link_speed); | ||
| 489 | |||
| 490 | static unsigned char agp_speeds[] = { | ||
| 491 | AGP_UNKNOWN, | ||
| 492 | AGP_1X, | ||
| 493 | AGP_2X, | ||
| 494 | AGP_4X, | ||
| 495 | AGP_8X | ||
| 496 | }; | ||
| 497 | |||
| 498 | static enum pci_bus_speed agp_speed(int agp3, int agpstat) | ||
| 499 | { | ||
| 500 | int index = 0; | ||
| 501 | |||
| 502 | if (agpstat & 4) | ||
| 503 | index = 3; | ||
| 504 | else if (agpstat & 2) | ||
| 505 | index = 2; | ||
| 506 | else if (agpstat & 1) | ||
| 507 | index = 1; | ||
| 508 | else | ||
| 509 | goto out; | ||
| 510 | |||
| 511 | if (agp3) { | ||
| 512 | index += 2; | ||
| 513 | if (index == 5) | ||
| 514 | index = 0; | ||
| 515 | } | ||
| 516 | |||
| 517 | out: | ||
| 518 | return agp_speeds[index]; | ||
| 519 | } | ||
| 520 | |||
| 521 | |||
| 522 | static void pci_set_bus_speed(struct pci_bus *bus) | ||
| 523 | { | ||
| 524 | struct pci_dev *bridge = bus->self; | ||
| 525 | int pos; | ||
| 526 | |||
| 527 | pos = pci_find_capability(bridge, PCI_CAP_ID_AGP); | ||
| 528 | if (!pos) | ||
| 529 | pos = pci_find_capability(bridge, PCI_CAP_ID_AGP3); | ||
| 530 | if (pos) { | ||
| 531 | u32 agpstat, agpcmd; | ||
| 532 | |||
| 533 | pci_read_config_dword(bridge, pos + PCI_AGP_STATUS, &agpstat); | ||
| 534 | bus->max_bus_speed = agp_speed(agpstat & 8, agpstat & 7); | ||
| 535 | |||
| 536 | pci_read_config_dword(bridge, pos + PCI_AGP_COMMAND, &agpcmd); | ||
| 537 | bus->cur_bus_speed = agp_speed(agpstat & 8, agpcmd & 7); | ||
| 538 | } | ||
| 539 | |||
| 540 | pos = pci_find_capability(bridge, PCI_CAP_ID_PCIX); | ||
| 541 | if (pos) { | ||
| 542 | u16 status; | ||
| 543 | enum pci_bus_speed max; | ||
| 544 | pci_read_config_word(bridge, pos + 2, &status); | ||
| 545 | |||
| 546 | if (status & 0x8000) { | ||
| 547 | max = PCI_SPEED_133MHz_PCIX_533; | ||
| 548 | } else if (status & 0x4000) { | ||
| 549 | max = PCI_SPEED_133MHz_PCIX_266; | ||
| 550 | } else if (status & 0x0002) { | ||
| 551 | if (((status >> 12) & 0x3) == 2) { | ||
| 552 | max = PCI_SPEED_133MHz_PCIX_ECC; | ||
| 553 | } else { | ||
| 554 | max = PCI_SPEED_133MHz_PCIX; | ||
| 555 | } | ||
| 556 | } else { | ||
| 557 | max = PCI_SPEED_66MHz_PCIX; | ||
| 558 | } | ||
| 559 | |||
| 560 | bus->max_bus_speed = max; | ||
| 561 | bus->cur_bus_speed = pcix_bus_speed[(status >> 6) & 0xf]; | ||
| 562 | |||
| 563 | return; | ||
| 564 | } | ||
| 565 | |||
| 566 | pos = pci_find_capability(bridge, PCI_CAP_ID_EXP); | ||
| 567 | if (pos) { | ||
| 568 | u32 linkcap; | ||
| 569 | u16 linksta; | ||
| 570 | |||
| 571 | pci_read_config_dword(bridge, pos + PCI_EXP_LNKCAP, &linkcap); | ||
| 572 | bus->max_bus_speed = pcie_link_speed[linkcap & 0xf]; | ||
| 573 | |||
| 574 | pci_read_config_word(bridge, pos + PCI_EXP_LNKSTA, &linksta); | ||
| 575 | pcie_update_link_speed(bus, linksta); | ||
| 576 | } | ||
| 577 | } | ||
| 578 | |||
| 579 | |||
| 394 | static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, | 580 | static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, |
| 395 | struct pci_dev *bridge, int busnr) | 581 | struct pci_dev *bridge, int busnr) |
| 396 | { | 582 | { |
| @@ -430,6 +616,8 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, | |||
| 430 | child->self = bridge; | 616 | child->self = bridge; |
| 431 | child->bridge = get_device(&bridge->dev); | 617 | child->bridge = get_device(&bridge->dev); |
| 432 | 618 | ||
| 619 | pci_set_bus_speed(child); | ||
| 620 | |||
| 433 | /* Set up default resource pointers and names.. */ | 621 | /* Set up default resource pointers and names.. */ |
| 434 | for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) { | 622 | for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) { |
| 435 | child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i]; | 623 | child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i]; |
| @@ -1081,6 +1269,45 @@ struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn) | |||
| 1081 | } | 1269 | } |
| 1082 | EXPORT_SYMBOL(pci_scan_single_device); | 1270 | EXPORT_SYMBOL(pci_scan_single_device); |
| 1083 | 1271 | ||
| 1272 | static unsigned next_ari_fn(struct pci_dev *dev, unsigned fn) | ||
| 1273 | { | ||
| 1274 | u16 cap; | ||
| 1275 | unsigned pos, next_fn; | ||
| 1276 | |||
| 1277 | if (!dev) | ||
| 1278 | return 0; | ||
| 1279 | |||
| 1280 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); | ||
| 1281 | if (!pos) | ||
| 1282 | return 0; | ||
| 1283 | pci_read_config_word(dev, pos + 4, &cap); | ||
| 1284 | next_fn = cap >> 8; | ||
| 1285 | if (next_fn <= fn) | ||
| 1286 | return 0; | ||
| 1287 | return next_fn; | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | static unsigned next_trad_fn(struct pci_dev *dev, unsigned fn) | ||
| 1291 | { | ||
| 1292 | return (fn + 1) % 8; | ||
| 1293 | } | ||
| 1294 | |||
| 1295 | static unsigned no_next_fn(struct pci_dev *dev, unsigned fn) | ||
| 1296 | { | ||
| 1297 | return 0; | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | static int only_one_child(struct pci_bus *bus) | ||
| 1301 | { | ||
| 1302 | struct pci_dev *parent = bus->self; | ||
| 1303 | if (!parent || !pci_is_pcie(parent)) | ||
| 1304 | return 0; | ||
| 1305 | if (parent->pcie_type == PCI_EXP_TYPE_ROOT_PORT || | ||
| 1306 | parent->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) | ||
| 1307 | return 1; | ||
| 1308 | return 0; | ||
| 1309 | } | ||
| 1310 | |||
| 1084 | /** | 1311 | /** |
| 1085 | * pci_scan_slot - scan a PCI slot on a bus for devices. | 1312 | * pci_scan_slot - scan a PCI slot on a bus for devices. |
| 1086 | * @bus: PCI bus to scan | 1313 | * @bus: PCI bus to scan |
| @@ -1094,21 +1321,30 @@ EXPORT_SYMBOL(pci_scan_single_device); | |||
| 1094 | */ | 1321 | */ |
| 1095 | int pci_scan_slot(struct pci_bus *bus, int devfn) | 1322 | int pci_scan_slot(struct pci_bus *bus, int devfn) |
| 1096 | { | 1323 | { |
| 1097 | int fn, nr = 0; | 1324 | unsigned fn, nr = 0; |
| 1098 | struct pci_dev *dev; | 1325 | struct pci_dev *dev; |
| 1326 | unsigned (*next_fn)(struct pci_dev *, unsigned) = no_next_fn; | ||
| 1327 | |||
| 1328 | if (only_one_child(bus) && (devfn > 0)) | ||
| 1329 | return 0; /* Already scanned the entire slot */ | ||
| 1099 | 1330 | ||
| 1100 | dev = pci_scan_single_device(bus, devfn); | 1331 | dev = pci_scan_single_device(bus, devfn); |
| 1101 | if (dev && !dev->is_added) /* new device? */ | 1332 | if (!dev) |
| 1333 | return 0; | ||
| 1334 | if (!dev->is_added) | ||
| 1102 | nr++; | 1335 | nr++; |
| 1103 | 1336 | ||
| 1104 | if (dev && dev->multifunction) { | 1337 | if (pci_ari_enabled(bus)) |
| 1105 | for (fn = 1; fn < 8; fn++) { | 1338 | next_fn = next_ari_fn; |
| 1106 | dev = pci_scan_single_device(bus, devfn + fn); | 1339 | else if (dev->multifunction) |
| 1107 | if (dev) { | 1340 | next_fn = next_trad_fn; |
| 1108 | if (!dev->is_added) | 1341 | |
| 1109 | nr++; | 1342 | for (fn = next_fn(dev, 0); fn > 0; fn = next_fn(dev, fn)) { |
| 1110 | dev->multifunction = 1; | 1343 | dev = pci_scan_single_device(bus, devfn + fn); |
| 1111 | } | 1344 | if (dev) { |
| 1345 | if (!dev->is_added) | ||
| 1346 | nr++; | ||
| 1347 | dev->multifunction = 1; | ||
| 1112 | } | 1348 | } |
| 1113 | } | 1349 | } |
| 1114 | 1350 | ||
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index d58b94030ef3..790eb69a4aa9 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
| @@ -25,14 +25,9 @@ | |||
| 25 | #include <linux/dmi.h> | 25 | #include <linux/dmi.h> |
| 26 | #include <linux/pci-aspm.h> | 26 | #include <linux/pci-aspm.h> |
| 27 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
| 28 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ | ||
| 28 | #include "pci.h" | 29 | #include "pci.h" |
| 29 | 30 | ||
| 30 | int isa_dma_bridge_buggy; | ||
| 31 | EXPORT_SYMBOL(isa_dma_bridge_buggy); | ||
| 32 | int pci_pci_problems; | ||
| 33 | EXPORT_SYMBOL(pci_pci_problems); | ||
| 34 | |||
| 35 | #ifdef CONFIG_PCI_QUIRKS | ||
| 36 | /* | 31 | /* |
| 37 | * This quirk function disables memory decoding and releases memory resources | 32 | * This quirk function disables memory decoding and releases memory resources |
| 38 | * of the device specified by kernel's boot parameter 'pci=resource_alignment='. | 33 | * of the device specified by kernel's boot parameter 'pci=resource_alignment='. |
| @@ -2612,6 +2607,7 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) | |||
| 2612 | } | 2607 | } |
| 2613 | pci_do_fixups(dev, start, end); | 2608 | pci_do_fixups(dev, start, end); |
| 2614 | } | 2609 | } |
| 2610 | EXPORT_SYMBOL(pci_fixup_device); | ||
| 2615 | 2611 | ||
| 2616 | static int __init pci_apply_final_quirks(void) | 2612 | static int __init pci_apply_final_quirks(void) |
| 2617 | { | 2613 | { |
| @@ -2723,9 +2719,3 @@ int pci_dev_specific_reset(struct pci_dev *dev, int probe) | |||
| 2723 | 2719 | ||
| 2724 | return -ENOTTY; | 2720 | return -ENOTTY; |
| 2725 | } | 2721 | } |
| 2726 | |||
| 2727 | #else | ||
| 2728 | void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {} | ||
| 2729 | int pci_dev_specific_reset(struct pci_dev *dev, int probe) { return -ENOTTY; } | ||
| 2730 | #endif | ||
| 2731 | EXPORT_SYMBOL(pci_fixup_device); | ||
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index c48cd377b3f5..bf32f07c4efb 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
| @@ -27,37 +27,83 @@ | |||
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | #include "pci.h" | 28 | #include "pci.h" |
| 29 | 29 | ||
| 30 | static void pbus_assign_resources_sorted(const struct pci_bus *bus) | 30 | struct resource_list_x { |
| 31 | { | 31 | struct resource_list_x *next; |
| 32 | struct pci_dev *dev; | ||
| 33 | struct resource *res; | 32 | struct resource *res; |
| 34 | struct resource_list head, *list, *tmp; | 33 | struct pci_dev *dev; |
| 35 | int idx; | 34 | resource_size_t start; |
| 35 | resource_size_t end; | ||
| 36 | unsigned long flags; | ||
| 37 | }; | ||
| 36 | 38 | ||
| 37 | head.next = NULL; | 39 | static void add_to_failed_list(struct resource_list_x *head, |
| 38 | list_for_each_entry(dev, &bus->devices, bus_list) { | 40 | struct pci_dev *dev, struct resource *res) |
| 39 | u16 class = dev->class >> 8; | 41 | { |
| 42 | struct resource_list_x *list = head; | ||
| 43 | struct resource_list_x *ln = list->next; | ||
| 44 | struct resource_list_x *tmp; | ||
| 40 | 45 | ||
| 41 | /* Don't touch classless devices or host bridges or ioapics. */ | 46 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); |
| 42 | if (class == PCI_CLASS_NOT_DEFINED || | 47 | if (!tmp) { |
| 43 | class == PCI_CLASS_BRIDGE_HOST) | 48 | pr_warning("add_to_failed_list: kmalloc() failed!\n"); |
| 44 | continue; | 49 | return; |
| 50 | } | ||
| 45 | 51 | ||
| 46 | /* Don't touch ioapic devices already enabled by firmware */ | 52 | tmp->next = ln; |
| 47 | if (class == PCI_CLASS_SYSTEM_PIC) { | 53 | tmp->res = res; |
| 48 | u16 command; | 54 | tmp->dev = dev; |
| 49 | pci_read_config_word(dev, PCI_COMMAND, &command); | 55 | tmp->start = res->start; |
| 50 | if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | 56 | tmp->end = res->end; |
| 51 | continue; | 57 | tmp->flags = res->flags; |
| 52 | } | 58 | list->next = tmp; |
| 59 | } | ||
| 60 | |||
| 61 | static void free_failed_list(struct resource_list_x *head) | ||
| 62 | { | ||
| 63 | struct resource_list_x *list, *tmp; | ||
| 53 | 64 | ||
| 54 | pdev_sort_resources(dev, &head); | 65 | for (list = head->next; list;) { |
| 66 | tmp = list; | ||
| 67 | list = list->next; | ||
| 68 | kfree(tmp); | ||
| 55 | } | 69 | } |
| 56 | 70 | ||
| 57 | for (list = head.next; list;) { | 71 | head->next = NULL; |
| 72 | } | ||
| 73 | |||
| 74 | static void __dev_sort_resources(struct pci_dev *dev, | ||
| 75 | struct resource_list *head) | ||
| 76 | { | ||
| 77 | u16 class = dev->class >> 8; | ||
| 78 | |||
| 79 | /* Don't touch classless devices or host bridges or ioapics. */ | ||
| 80 | if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST) | ||
| 81 | return; | ||
| 82 | |||
| 83 | /* Don't touch ioapic devices already enabled by firmware */ | ||
| 84 | if (class == PCI_CLASS_SYSTEM_PIC) { | ||
| 85 | u16 command; | ||
| 86 | pci_read_config_word(dev, PCI_COMMAND, &command); | ||
| 87 | if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | ||
| 88 | return; | ||
| 89 | } | ||
| 90 | |||
| 91 | pdev_sort_resources(dev, head); | ||
| 92 | } | ||
| 93 | |||
| 94 | static void __assign_resources_sorted(struct resource_list *head, | ||
| 95 | struct resource_list_x *fail_head) | ||
| 96 | { | ||
| 97 | struct resource *res; | ||
| 98 | struct resource_list *list, *tmp; | ||
| 99 | int idx; | ||
| 100 | |||
| 101 | for (list = head->next; list;) { | ||
| 58 | res = list->res; | 102 | res = list->res; |
| 59 | idx = res - &list->dev->resource[0]; | 103 | idx = res - &list->dev->resource[0]; |
| 60 | if (pci_assign_resource(list->dev, idx)) { | 104 | if (pci_assign_resource(list->dev, idx)) { |
| 105 | if (fail_head && !pci_is_root_bus(list->dev->bus)) | ||
| 106 | add_to_failed_list(fail_head, list->dev, res); | ||
| 61 | res->start = 0; | 107 | res->start = 0; |
| 62 | res->end = 0; | 108 | res->end = 0; |
| 63 | res->flags = 0; | 109 | res->flags = 0; |
| @@ -68,6 +114,30 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus) | |||
| 68 | } | 114 | } |
| 69 | } | 115 | } |
| 70 | 116 | ||
| 117 | static void pdev_assign_resources_sorted(struct pci_dev *dev, | ||
| 118 | struct resource_list_x *fail_head) | ||
| 119 | { | ||
| 120 | struct resource_list head; | ||
| 121 | |||
| 122 | head.next = NULL; | ||
| 123 | __dev_sort_resources(dev, &head); | ||
| 124 | __assign_resources_sorted(&head, fail_head); | ||
| 125 | |||
| 126 | } | ||
| 127 | |||
| 128 | static void pbus_assign_resources_sorted(const struct pci_bus *bus, | ||
| 129 | struct resource_list_x *fail_head) | ||
| 130 | { | ||
| 131 | struct pci_dev *dev; | ||
| 132 | struct resource_list head; | ||
| 133 | |||
| 134 | head.next = NULL; | ||
| 135 | list_for_each_entry(dev, &bus->devices, bus_list) | ||
| 136 | __dev_sort_resources(dev, &head); | ||
| 137 | |||
| 138 | __assign_resources_sorted(&head, fail_head); | ||
| 139 | } | ||
| 140 | |||
| 71 | void pci_setup_cardbus(struct pci_bus *bus) | 141 | void pci_setup_cardbus(struct pci_bus *bus) |
| 72 | { | 142 | { |
| 73 | struct pci_dev *bridge = bus->self; | 143 | struct pci_dev *bridge = bus->self; |
| @@ -134,18 +204,12 @@ EXPORT_SYMBOL(pci_setup_cardbus); | |||
| 134 | config space writes, so it's quite possible that an I/O window of | 204 | config space writes, so it's quite possible that an I/O window of |
| 135 | the bridge will have some undesirable address (e.g. 0) after the | 205 | the bridge will have some undesirable address (e.g. 0) after the |
| 136 | first write. Ditto 64-bit prefetchable MMIO. */ | 206 | first write. Ditto 64-bit prefetchable MMIO. */ |
| 137 | static void pci_setup_bridge(struct pci_bus *bus) | 207 | static void pci_setup_bridge_io(struct pci_bus *bus) |
| 138 | { | 208 | { |
| 139 | struct pci_dev *bridge = bus->self; | 209 | struct pci_dev *bridge = bus->self; |
| 140 | struct resource *res; | 210 | struct resource *res; |
| 141 | struct pci_bus_region region; | 211 | struct pci_bus_region region; |
| 142 | u32 l, bu, lu, io_upper16; | 212 | u32 l, io_upper16; |
| 143 | |||
| 144 | if (pci_is_enabled(bridge)) | ||
| 145 | return; | ||
| 146 | |||
| 147 | dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n", | ||
| 148 | bus->secondary, bus->subordinate); | ||
| 149 | 213 | ||
| 150 | /* Set up the top and bottom of the PCI I/O segment for this bus. */ | 214 | /* Set up the top and bottom of the PCI I/O segment for this bus. */ |
| 151 | res = bus->resource[0]; | 215 | res = bus->resource[0]; |
| @@ -158,8 +222,7 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
| 158 | /* Set up upper 16 bits of I/O base/limit. */ | 222 | /* Set up upper 16 bits of I/O base/limit. */ |
| 159 | io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); | 223 | io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); |
| 160 | dev_info(&bridge->dev, " bridge window %pR\n", res); | 224 | dev_info(&bridge->dev, " bridge window %pR\n", res); |
| 161 | } | 225 | } else { |
| 162 | else { | ||
| 163 | /* Clear upper 16 bits of I/O base/limit. */ | 226 | /* Clear upper 16 bits of I/O base/limit. */ |
| 164 | io_upper16 = 0; | 227 | io_upper16 = 0; |
| 165 | l = 0x00f0; | 228 | l = 0x00f0; |
| @@ -171,21 +234,35 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
| 171 | pci_write_config_dword(bridge, PCI_IO_BASE, l); | 234 | pci_write_config_dword(bridge, PCI_IO_BASE, l); |
| 172 | /* Update upper 16 bits of I/O base/limit. */ | 235 | /* Update upper 16 bits of I/O base/limit. */ |
| 173 | pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16); | 236 | pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16); |
| 237 | } | ||
| 174 | 238 | ||
| 175 | /* Set up the top and bottom of the PCI Memory segment | 239 | static void pci_setup_bridge_mmio(struct pci_bus *bus) |
| 176 | for this bus. */ | 240 | { |
| 241 | struct pci_dev *bridge = bus->self; | ||
| 242 | struct resource *res; | ||
| 243 | struct pci_bus_region region; | ||
| 244 | u32 l; | ||
| 245 | |||
| 246 | /* Set up the top and bottom of the PCI Memory segment for this bus. */ | ||
| 177 | res = bus->resource[1]; | 247 | res = bus->resource[1]; |
| 178 | pcibios_resource_to_bus(bridge, ®ion, res); | 248 | pcibios_resource_to_bus(bridge, ®ion, res); |
| 179 | if (res->flags & IORESOURCE_MEM) { | 249 | if (res->flags & IORESOURCE_MEM) { |
| 180 | l = (region.start >> 16) & 0xfff0; | 250 | l = (region.start >> 16) & 0xfff0; |
| 181 | l |= region.end & 0xfff00000; | 251 | l |= region.end & 0xfff00000; |
| 182 | dev_info(&bridge->dev, " bridge window %pR\n", res); | 252 | dev_info(&bridge->dev, " bridge window %pR\n", res); |
| 183 | } | 253 | } else { |
| 184 | else { | ||
| 185 | l = 0x0000fff0; | 254 | l = 0x0000fff0; |
| 186 | dev_info(&bridge->dev, " bridge window [mem disabled]\n"); | 255 | dev_info(&bridge->dev, " bridge window [mem disabled]\n"); |
| 187 | } | 256 | } |
| 188 | pci_write_config_dword(bridge, PCI_MEMORY_BASE, l); | 257 | pci_write_config_dword(bridge, PCI_MEMORY_BASE, l); |
| 258 | } | ||
| 259 | |||
| 260 | static void pci_setup_bridge_mmio_pref(struct pci_bus *bus) | ||
| 261 | { | ||
| 262 | struct pci_dev *bridge = bus->self; | ||
| 263 | struct resource *res; | ||
| 264 | struct pci_bus_region region; | ||
| 265 | u32 l, bu, lu; | ||
| 189 | 266 | ||
| 190 | /* Clear out the upper 32 bits of PREF limit. | 267 | /* Clear out the upper 32 bits of PREF limit. |
| 191 | If PCI_PREF_BASE_UPPER32 was non-zero, this temporarily | 268 | If PCI_PREF_BASE_UPPER32 was non-zero, this temporarily |
| @@ -204,8 +281,7 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
| 204 | lu = upper_32_bits(region.end); | 281 | lu = upper_32_bits(region.end); |
| 205 | } | 282 | } |
| 206 | dev_info(&bridge->dev, " bridge window %pR\n", res); | 283 | dev_info(&bridge->dev, " bridge window %pR\n", res); |
| 207 | } | 284 | } else { |
| 208 | else { | ||
| 209 | l = 0x0000fff0; | 285 | l = 0x0000fff0; |
| 210 | dev_info(&bridge->dev, " bridge window [mem pref disabled]\n"); | 286 | dev_info(&bridge->dev, " bridge window [mem pref disabled]\n"); |
| 211 | } | 287 | } |
| @@ -214,10 +290,35 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
| 214 | /* Set the upper 32 bits of PREF base & limit. */ | 290 | /* Set the upper 32 bits of PREF base & limit. */ |
| 215 | pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); | 291 | pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); |
| 216 | pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); | 292 | pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); |
| 293 | } | ||
| 294 | |||
| 295 | static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type) | ||
| 296 | { | ||
| 297 | struct pci_dev *bridge = bus->self; | ||
| 298 | |||
| 299 | dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n", | ||
| 300 | bus->secondary, bus->subordinate); | ||
| 301 | |||
| 302 | if (type & IORESOURCE_IO) | ||
| 303 | pci_setup_bridge_io(bus); | ||
| 304 | |||
| 305 | if (type & IORESOURCE_MEM) | ||
| 306 | pci_setup_bridge_mmio(bus); | ||
| 307 | |||
| 308 | if (type & IORESOURCE_PREFETCH) | ||
| 309 | pci_setup_bridge_mmio_pref(bus); | ||
| 217 | 310 | ||
| 218 | pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); | 311 | pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); |
| 219 | } | 312 | } |
| 220 | 313 | ||
| 314 | static void pci_setup_bridge(struct pci_bus *bus) | ||
| 315 | { | ||
| 316 | unsigned long type = IORESOURCE_IO | IORESOURCE_MEM | | ||
| 317 | IORESOURCE_PREFETCH; | ||
| 318 | |||
| 319 | __pci_setup_bridge(bus, type); | ||
| 320 | } | ||
| 321 | |||
| 221 | /* Check whether the bridge supports optional I/O and | 322 | /* Check whether the bridge supports optional I/O and |
| 222 | prefetchable memory ranges. If not, the respective | 323 | prefetchable memory ranges. If not, the respective |
| 223 | base/limit registers must be read-only and read as 0. */ | 324 | base/limit registers must be read-only and read as 0. */ |
| @@ -253,8 +354,11 @@ static void pci_bridge_check_ranges(struct pci_bus *bus) | |||
| 253 | } | 354 | } |
| 254 | if (pmem) { | 355 | if (pmem) { |
| 255 | b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; | 356 | b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; |
| 256 | if ((pmem & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) | 357 | if ((pmem & PCI_PREF_RANGE_TYPE_MASK) == |
| 358 | PCI_PREF_RANGE_TYPE_64) { | ||
| 257 | b_res[2].flags |= IORESOURCE_MEM_64; | 359 | b_res[2].flags |= IORESOURCE_MEM_64; |
| 360 | b_res[2].flags |= PCI_PREF_RANGE_TYPE_64; | ||
| 361 | } | ||
| 258 | } | 362 | } |
| 259 | 363 | ||
| 260 | /* double check if bridge does support 64 bit pref */ | 364 | /* double check if bridge does support 64 bit pref */ |
| @@ -283,8 +387,7 @@ static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned lon | |||
| 283 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | 387 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | |
| 284 | IORESOURCE_PREFETCH; | 388 | IORESOURCE_PREFETCH; |
| 285 | 389 | ||
| 286 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | 390 | pci_bus_for_each_resource(bus, r, i) { |
| 287 | r = bus->resource[i]; | ||
| 288 | if (r == &ioport_resource || r == &iomem_resource) | 391 | if (r == &ioport_resource || r == &iomem_resource) |
| 289 | continue; | 392 | continue; |
| 290 | if (r && (r->flags & type_mask) == type && !r->parent) | 393 | if (r && (r->flags & type_mask) == type && !r->parent) |
| @@ -301,7 +404,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) | |||
| 301 | { | 404 | { |
| 302 | struct pci_dev *dev; | 405 | struct pci_dev *dev; |
| 303 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); | 406 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); |
| 304 | unsigned long size = 0, size1 = 0; | 407 | unsigned long size = 0, size1 = 0, old_size; |
| 305 | 408 | ||
| 306 | if (!b_res) | 409 | if (!b_res) |
| 307 | return; | 410 | return; |
| @@ -326,12 +429,17 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) | |||
| 326 | } | 429 | } |
| 327 | if (size < min_size) | 430 | if (size < min_size) |
| 328 | size = min_size; | 431 | size = min_size; |
| 432 | old_size = resource_size(b_res); | ||
| 433 | if (old_size == 1) | ||
| 434 | old_size = 0; | ||
| 329 | /* To be fixed in 2.5: we should have sort of HAVE_ISA | 435 | /* To be fixed in 2.5: we should have sort of HAVE_ISA |
| 330 | flag in the struct pci_bus. */ | 436 | flag in the struct pci_bus. */ |
| 331 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) | 437 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) |
| 332 | size = (size & 0xff) + ((size & ~0xffUL) << 2); | 438 | size = (size & 0xff) + ((size & ~0xffUL) << 2); |
| 333 | #endif | 439 | #endif |
| 334 | size = ALIGN(size + size1, 4096); | 440 | size = ALIGN(size + size1, 4096); |
| 441 | if (size < old_size) | ||
| 442 | size = old_size; | ||
| 335 | if (!size) { | 443 | if (!size) { |
| 336 | if (b_res->start || b_res->end) | 444 | if (b_res->start || b_res->end) |
| 337 | dev_info(&bus->self->dev, "disabling bridge window " | 445 | dev_info(&bus->self->dev, "disabling bridge window " |
| @@ -352,7 +460,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
| 352 | unsigned long type, resource_size_t min_size) | 460 | unsigned long type, resource_size_t min_size) |
| 353 | { | 461 | { |
| 354 | struct pci_dev *dev; | 462 | struct pci_dev *dev; |
| 355 | resource_size_t min_align, align, size; | 463 | resource_size_t min_align, align, size, old_size; |
| 356 | resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ | 464 | resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ |
| 357 | int order, max_order; | 465 | int order, max_order; |
| 358 | struct resource *b_res = find_free_bus_resource(bus, type); | 466 | struct resource *b_res = find_free_bus_resource(bus, type); |
| @@ -402,6 +510,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
| 402 | } | 510 | } |
| 403 | if (size < min_size) | 511 | if (size < min_size) |
| 404 | size = min_size; | 512 | size = min_size; |
| 513 | old_size = resource_size(b_res); | ||
| 514 | if (old_size == 1) | ||
| 515 | old_size = 0; | ||
| 516 | if (size < old_size) | ||
| 517 | size = old_size; | ||
| 405 | 518 | ||
| 406 | align = 0; | 519 | align = 0; |
| 407 | min_align = 0; | 520 | min_align = 0; |
| @@ -538,23 +651,25 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus) | |||
| 538 | } | 651 | } |
| 539 | EXPORT_SYMBOL(pci_bus_size_bridges); | 652 | EXPORT_SYMBOL(pci_bus_size_bridges); |
| 540 | 653 | ||
| 541 | void __ref pci_bus_assign_resources(const struct pci_bus *bus) | 654 | static void __ref __pci_bus_assign_resources(const struct pci_bus *bus, |
| 655 | struct resource_list_x *fail_head) | ||
| 542 | { | 656 | { |
| 543 | struct pci_bus *b; | 657 | struct pci_bus *b; |
| 544 | struct pci_dev *dev; | 658 | struct pci_dev *dev; |
| 545 | 659 | ||
| 546 | pbus_assign_resources_sorted(bus); | 660 | pbus_assign_resources_sorted(bus, fail_head); |
| 547 | 661 | ||
| 548 | list_for_each_entry(dev, &bus->devices, bus_list) { | 662 | list_for_each_entry(dev, &bus->devices, bus_list) { |
| 549 | b = dev->subordinate; | 663 | b = dev->subordinate; |
| 550 | if (!b) | 664 | if (!b) |
| 551 | continue; | 665 | continue; |
| 552 | 666 | ||
| 553 | pci_bus_assign_resources(b); | 667 | __pci_bus_assign_resources(b, fail_head); |
| 554 | 668 | ||
| 555 | switch (dev->class >> 8) { | 669 | switch (dev->class >> 8) { |
| 556 | case PCI_CLASS_BRIDGE_PCI: | 670 | case PCI_CLASS_BRIDGE_PCI: |
| 557 | pci_setup_bridge(b); | 671 | if (!pci_is_enabled(dev)) |
| 672 | pci_setup_bridge(b); | ||
| 558 | break; | 673 | break; |
| 559 | 674 | ||
| 560 | case PCI_CLASS_BRIDGE_CARDBUS: | 675 | case PCI_CLASS_BRIDGE_CARDBUS: |
| @@ -568,15 +683,130 @@ void __ref pci_bus_assign_resources(const struct pci_bus *bus) | |||
| 568 | } | 683 | } |
| 569 | } | 684 | } |
| 570 | } | 685 | } |
| 686 | |||
| 687 | void __ref pci_bus_assign_resources(const struct pci_bus *bus) | ||
| 688 | { | ||
| 689 | __pci_bus_assign_resources(bus, NULL); | ||
| 690 | } | ||
| 571 | EXPORT_SYMBOL(pci_bus_assign_resources); | 691 | EXPORT_SYMBOL(pci_bus_assign_resources); |
| 572 | 692 | ||
| 693 | static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge, | ||
| 694 | struct resource_list_x *fail_head) | ||
| 695 | { | ||
| 696 | struct pci_bus *b; | ||
| 697 | |||
| 698 | pdev_assign_resources_sorted((struct pci_dev *)bridge, fail_head); | ||
| 699 | |||
| 700 | b = bridge->subordinate; | ||
| 701 | if (!b) | ||
| 702 | return; | ||
| 703 | |||
| 704 | __pci_bus_assign_resources(b, fail_head); | ||
| 705 | |||
| 706 | switch (bridge->class >> 8) { | ||
| 707 | case PCI_CLASS_BRIDGE_PCI: | ||
| 708 | pci_setup_bridge(b); | ||
| 709 | break; | ||
| 710 | |||
| 711 | case PCI_CLASS_BRIDGE_CARDBUS: | ||
| 712 | pci_setup_cardbus(b); | ||
| 713 | break; | ||
| 714 | |||
| 715 | default: | ||
| 716 | dev_info(&bridge->dev, "not setting up bridge for bus " | ||
| 717 | "%04x:%02x\n", pci_domain_nr(b), b->number); | ||
| 718 | break; | ||
| 719 | } | ||
| 720 | } | ||
| 721 | static void pci_bridge_release_resources(struct pci_bus *bus, | ||
| 722 | unsigned long type) | ||
| 723 | { | ||
| 724 | int idx; | ||
| 725 | bool changed = false; | ||
| 726 | struct pci_dev *dev; | ||
| 727 | struct resource *r; | ||
| 728 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | ||
| 729 | IORESOURCE_PREFETCH; | ||
| 730 | |||
| 731 | dev = bus->self; | ||
| 732 | for (idx = PCI_BRIDGE_RESOURCES; idx <= PCI_BRIDGE_RESOURCE_END; | ||
| 733 | idx++) { | ||
| 734 | r = &dev->resource[idx]; | ||
| 735 | if ((r->flags & type_mask) != type) | ||
| 736 | continue; | ||
| 737 | if (!r->parent) | ||
| 738 | continue; | ||
| 739 | /* | ||
| 740 | * if there are children under that, we should release them | ||
| 741 | * all | ||
| 742 | */ | ||
| 743 | release_child_resources(r); | ||
| 744 | if (!release_resource(r)) { | ||
| 745 | dev_printk(KERN_DEBUG, &dev->dev, | ||
| 746 | "resource %d %pR released\n", idx, r); | ||
| 747 | /* keep the old size */ | ||
| 748 | r->end = resource_size(r) - 1; | ||
| 749 | r->start = 0; | ||
| 750 | r->flags = 0; | ||
| 751 | changed = true; | ||
| 752 | } | ||
| 753 | } | ||
| 754 | |||
| 755 | if (changed) { | ||
| 756 | /* avoiding touch the one without PREF */ | ||
| 757 | if (type & IORESOURCE_PREFETCH) | ||
| 758 | type = IORESOURCE_PREFETCH; | ||
| 759 | __pci_setup_bridge(bus, type); | ||
| 760 | } | ||
| 761 | } | ||
| 762 | |||
| 763 | enum release_type { | ||
| 764 | leaf_only, | ||
| 765 | whole_subtree, | ||
| 766 | }; | ||
| 767 | /* | ||
| 768 | * try to release pci bridge resources that is from leaf bridge, | ||
| 769 | * so we can allocate big new one later | ||
| 770 | */ | ||
| 771 | static void __ref pci_bus_release_bridge_resources(struct pci_bus *bus, | ||
| 772 | unsigned long type, | ||
| 773 | enum release_type rel_type) | ||
| 774 | { | ||
| 775 | struct pci_dev *dev; | ||
| 776 | bool is_leaf_bridge = true; | ||
| 777 | |||
| 778 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
| 779 | struct pci_bus *b = dev->subordinate; | ||
| 780 | if (!b) | ||
| 781 | continue; | ||
| 782 | |||
| 783 | is_leaf_bridge = false; | ||
| 784 | |||
| 785 | if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) | ||
| 786 | continue; | ||
| 787 | |||
| 788 | if (rel_type == whole_subtree) | ||
| 789 | pci_bus_release_bridge_resources(b, type, | ||
| 790 | whole_subtree); | ||
| 791 | } | ||
| 792 | |||
| 793 | if (pci_is_root_bus(bus)) | ||
| 794 | return; | ||
| 795 | |||
| 796 | if ((bus->self->class >> 8) != PCI_CLASS_BRIDGE_PCI) | ||
| 797 | return; | ||
| 798 | |||
| 799 | if ((rel_type == whole_subtree) || is_leaf_bridge) | ||
| 800 | pci_bridge_release_resources(bus, type); | ||
| 801 | } | ||
| 802 | |||
| 573 | static void pci_bus_dump_res(struct pci_bus *bus) | 803 | static void pci_bus_dump_res(struct pci_bus *bus) |
| 574 | { | 804 | { |
| 575 | int i; | 805 | struct resource *res; |
| 806 | int i; | ||
| 576 | 807 | ||
| 577 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | 808 | pci_bus_for_each_resource(bus, res, i) { |
| 578 | struct resource *res = bus->resource[i]; | 809 | if (!res || !res->end || !res->flags) |
| 579 | if (!res || !res->end) | ||
| 580 | continue; | 810 | continue; |
| 581 | 811 | ||
| 582 | dev_printk(KERN_DEBUG, &bus->dev, "resource %d %pR\n", i, res); | 812 | dev_printk(KERN_DEBUG, &bus->dev, "resource %d %pR\n", i, res); |
| @@ -600,11 +830,65 @@ static void pci_bus_dump_resources(struct pci_bus *bus) | |||
| 600 | } | 830 | } |
| 601 | } | 831 | } |
| 602 | 832 | ||
| 833 | static int __init pci_bus_get_depth(struct pci_bus *bus) | ||
| 834 | { | ||
| 835 | int depth = 0; | ||
| 836 | struct pci_dev *dev; | ||
| 837 | |||
| 838 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
| 839 | int ret; | ||
| 840 | struct pci_bus *b = dev->subordinate; | ||
| 841 | if (!b) | ||
| 842 | continue; | ||
| 843 | |||
| 844 | ret = pci_bus_get_depth(b); | ||
| 845 | if (ret + 1 > depth) | ||
| 846 | depth = ret + 1; | ||
| 847 | } | ||
| 848 | |||
| 849 | return depth; | ||
| 850 | } | ||
| 851 | static int __init pci_get_max_depth(void) | ||
| 852 | { | ||
| 853 | int depth = 0; | ||
| 854 | struct pci_bus *bus; | ||
| 855 | |||
| 856 | list_for_each_entry(bus, &pci_root_buses, node) { | ||
| 857 | int ret; | ||
| 858 | |||
| 859 | ret = pci_bus_get_depth(bus); | ||
| 860 | if (ret > depth) | ||
| 861 | depth = ret; | ||
| 862 | } | ||
| 863 | |||
| 864 | return depth; | ||
| 865 | } | ||
| 866 | |||
| 867 | /* | ||
| 868 | * first try will not touch pci bridge res | ||
| 869 | * second and later try will clear small leaf bridge res | ||
| 870 | * will stop till to the max deepth if can not find good one | ||
| 871 | */ | ||
| 603 | void __init | 872 | void __init |
| 604 | pci_assign_unassigned_resources(void) | 873 | pci_assign_unassigned_resources(void) |
| 605 | { | 874 | { |
| 606 | struct pci_bus *bus; | 875 | struct pci_bus *bus; |
| 876 | int tried_times = 0; | ||
| 877 | enum release_type rel_type = leaf_only; | ||
| 878 | struct resource_list_x head, *list; | ||
| 879 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | ||
| 880 | IORESOURCE_PREFETCH; | ||
| 881 | unsigned long failed_type; | ||
| 882 | int max_depth = pci_get_max_depth(); | ||
| 883 | int pci_try_num; | ||
| 607 | 884 | ||
| 885 | head.next = NULL; | ||
| 886 | |||
| 887 | pci_try_num = max_depth + 1; | ||
| 888 | printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n", | ||
| 889 | max_depth, pci_try_num); | ||
| 890 | |||
| 891 | again: | ||
| 608 | /* Depth first, calculate sizes and alignments of all | 892 | /* Depth first, calculate sizes and alignments of all |
| 609 | subordinate buses. */ | 893 | subordinate buses. */ |
| 610 | list_for_each_entry(bus, &pci_root_buses, node) { | 894 | list_for_each_entry(bus, &pci_root_buses, node) { |
| @@ -612,12 +896,130 @@ pci_assign_unassigned_resources(void) | |||
| 612 | } | 896 | } |
| 613 | /* Depth last, allocate resources and update the hardware. */ | 897 | /* Depth last, allocate resources and update the hardware. */ |
| 614 | list_for_each_entry(bus, &pci_root_buses, node) { | 898 | list_for_each_entry(bus, &pci_root_buses, node) { |
| 615 | pci_bus_assign_resources(bus); | 899 | __pci_bus_assign_resources(bus, &head); |
| 616 | pci_enable_bridges(bus); | ||
| 617 | } | 900 | } |
| 901 | tried_times++; | ||
| 902 | |||
| 903 | /* any device complain? */ | ||
| 904 | if (!head.next) | ||
| 905 | goto enable_and_dump; | ||
| 906 | failed_type = 0; | ||
| 907 | for (list = head.next; list;) { | ||
| 908 | failed_type |= list->flags; | ||
| 909 | list = list->next; | ||
| 910 | } | ||
| 911 | /* | ||
| 912 | * io port are tight, don't try extra | ||
| 913 | * or if reach the limit, don't want to try more | ||
| 914 | */ | ||
| 915 | failed_type &= type_mask; | ||
| 916 | if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) { | ||
| 917 | free_failed_list(&head); | ||
| 918 | goto enable_and_dump; | ||
| 919 | } | ||
| 920 | |||
| 921 | printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", | ||
| 922 | tried_times + 1); | ||
| 923 | |||
| 924 | /* third times and later will not check if it is leaf */ | ||
| 925 | if ((tried_times + 1) > 2) | ||
| 926 | rel_type = whole_subtree; | ||
| 927 | |||
| 928 | /* | ||
| 929 | * Try to release leaf bridge's resources that doesn't fit resource of | ||
| 930 | * child device under that bridge | ||
| 931 | */ | ||
| 932 | for (list = head.next; list;) { | ||
| 933 | bus = list->dev->bus; | ||
| 934 | pci_bus_release_bridge_resources(bus, list->flags & type_mask, | ||
| 935 | rel_type); | ||
| 936 | list = list->next; | ||
| 937 | } | ||
| 938 | /* restore size and flags */ | ||
| 939 | for (list = head.next; list;) { | ||
| 940 | struct resource *res = list->res; | ||
| 941 | |||
| 942 | res->start = list->start; | ||
| 943 | res->end = list->end; | ||
| 944 | res->flags = list->flags; | ||
| 945 | if (list->dev->subordinate) | ||
| 946 | res->flags = 0; | ||
| 947 | |||
| 948 | list = list->next; | ||
| 949 | } | ||
| 950 | free_failed_list(&head); | ||
| 951 | |||
| 952 | goto again; | ||
| 953 | |||
| 954 | enable_and_dump: | ||
| 955 | /* Depth last, update the hardware. */ | ||
| 956 | list_for_each_entry(bus, &pci_root_buses, node) | ||
| 957 | pci_enable_bridges(bus); | ||
| 618 | 958 | ||
| 619 | /* dump the resource on buses */ | 959 | /* dump the resource on buses */ |
| 620 | list_for_each_entry(bus, &pci_root_buses, node) { | 960 | list_for_each_entry(bus, &pci_root_buses, node) { |
| 621 | pci_bus_dump_resources(bus); | 961 | pci_bus_dump_resources(bus); |
| 622 | } | 962 | } |
| 623 | } | 963 | } |
| 964 | |||
| 965 | void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) | ||
| 966 | { | ||
| 967 | struct pci_bus *parent = bridge->subordinate; | ||
| 968 | int tried_times = 0; | ||
| 969 | struct resource_list_x head, *list; | ||
| 970 | int retval; | ||
| 971 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | ||
| 972 | IORESOURCE_PREFETCH; | ||
| 973 | |||
| 974 | head.next = NULL; | ||
| 975 | |||
| 976 | again: | ||
| 977 | pci_bus_size_bridges(parent); | ||
| 978 | __pci_bridge_assign_resources(bridge, &head); | ||
| 979 | retval = pci_reenable_device(bridge); | ||
| 980 | pci_set_master(bridge); | ||
| 981 | pci_enable_bridges(parent); | ||
| 982 | |||
| 983 | tried_times++; | ||
| 984 | |||
| 985 | if (!head.next) | ||
| 986 | return; | ||
| 987 | |||
| 988 | if (tried_times >= 2) { | ||
| 989 | /* still fail, don't need to try more */ | ||
| 990 | free_failed_list(&head); | ||
| 991 | return; | ||
| 992 | } | ||
| 993 | |||
| 994 | printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", | ||
| 995 | tried_times + 1); | ||
| 996 | |||
| 997 | /* | ||
| 998 | * Try to release leaf bridge's resources that doesn't fit resource of | ||
| 999 | * child device under that bridge | ||
| 1000 | */ | ||
| 1001 | for (list = head.next; list;) { | ||
| 1002 | struct pci_bus *bus = list->dev->bus; | ||
| 1003 | unsigned long flags = list->flags; | ||
| 1004 | |||
| 1005 | pci_bus_release_bridge_resources(bus, flags & type_mask, | ||
| 1006 | whole_subtree); | ||
| 1007 | list = list->next; | ||
| 1008 | } | ||
| 1009 | /* restore size and flags */ | ||
| 1010 | for (list = head.next; list;) { | ||
| 1011 | struct resource *res = list->res; | ||
| 1012 | |||
| 1013 | res->start = list->start; | ||
| 1014 | res->end = list->end; | ||
| 1015 | res->flags = list->flags; | ||
| 1016 | if (list->dev->subordinate) | ||
| 1017 | res->flags = 0; | ||
| 1018 | |||
| 1019 | list = list->next; | ||
| 1020 | } | ||
| 1021 | free_failed_list(&head); | ||
| 1022 | |||
| 1023 | goto again; | ||
| 1024 | } | ||
| 1025 | EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources); | ||
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index 8c02b6c53bdb..49c9e6c9779a 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c | |||
| @@ -47,6 +47,55 @@ static ssize_t address_read_file(struct pci_slot *slot, char *buf) | |||
| 47 | slot->number); | 47 | slot->number); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | /* these strings match up with the values in pci_bus_speed */ | ||
| 51 | static char *pci_bus_speed_strings[] = { | ||
| 52 | "33 MHz PCI", /* 0x00 */ | ||
| 53 | "66 MHz PCI", /* 0x01 */ | ||
| 54 | "66 MHz PCI-X", /* 0x02 */ | ||
| 55 | "100 MHz PCI-X", /* 0x03 */ | ||
| 56 | "133 MHz PCI-X", /* 0x04 */ | ||
| 57 | NULL, /* 0x05 */ | ||
| 58 | NULL, /* 0x06 */ | ||
| 59 | NULL, /* 0x07 */ | ||
| 60 | NULL, /* 0x08 */ | ||
| 61 | "66 MHz PCI-X 266", /* 0x09 */ | ||
| 62 | "100 MHz PCI-X 266", /* 0x0a */ | ||
| 63 | "133 MHz PCI-X 266", /* 0x0b */ | ||
| 64 | "Unknown AGP", /* 0x0c */ | ||
| 65 | "1x AGP", /* 0x0d */ | ||
| 66 | "2x AGP", /* 0x0e */ | ||
| 67 | "4x AGP", /* 0x0f */ | ||
| 68 | "8x AGP", /* 0x10 */ | ||
| 69 | "66 MHz PCI-X 533", /* 0x11 */ | ||
| 70 | "100 MHz PCI-X 533", /* 0x12 */ | ||
| 71 | "133 MHz PCI-X 533", /* 0x13 */ | ||
| 72 | "2.5 GT/s PCIe", /* 0x14 */ | ||
| 73 | "5.0 GT/s PCIe", /* 0x15 */ | ||
| 74 | "8.0 GT/s PCIe", /* 0x16 */ | ||
| 75 | }; | ||
| 76 | |||
| 77 | static ssize_t bus_speed_read(enum pci_bus_speed speed, char *buf) | ||
| 78 | { | ||
| 79 | const char *speed_string; | ||
| 80 | |||
| 81 | if (speed < ARRAY_SIZE(pci_bus_speed_strings)) | ||
| 82 | speed_string = pci_bus_speed_strings[speed]; | ||
| 83 | else | ||
| 84 | speed_string = "Unknown"; | ||
| 85 | |||
| 86 | return sprintf(buf, "%s\n", speed_string); | ||
| 87 | } | ||
| 88 | |||
| 89 | static ssize_t max_speed_read_file(struct pci_slot *slot, char *buf) | ||
| 90 | { | ||
| 91 | return bus_speed_read(slot->bus->max_bus_speed, buf); | ||
| 92 | } | ||
| 93 | |||
| 94 | static ssize_t cur_speed_read_file(struct pci_slot *slot, char *buf) | ||
| 95 | { | ||
| 96 | return bus_speed_read(slot->bus->cur_bus_speed, buf); | ||
| 97 | } | ||
| 98 | |||
| 50 | static void pci_slot_release(struct kobject *kobj) | 99 | static void pci_slot_release(struct kobject *kobj) |
| 51 | { | 100 | { |
| 52 | struct pci_dev *dev; | 101 | struct pci_dev *dev; |
| @@ -66,9 +115,15 @@ static void pci_slot_release(struct kobject *kobj) | |||
| 66 | 115 | ||
| 67 | static struct pci_slot_attribute pci_slot_attr_address = | 116 | static struct pci_slot_attribute pci_slot_attr_address = |
| 68 | __ATTR(address, (S_IFREG | S_IRUGO), address_read_file, NULL); | 117 | __ATTR(address, (S_IFREG | S_IRUGO), address_read_file, NULL); |
| 118 | static struct pci_slot_attribute pci_slot_attr_max_speed = | ||
| 119 | __ATTR(max_bus_speed, (S_IFREG | S_IRUGO), max_speed_read_file, NULL); | ||
| 120 | static struct pci_slot_attribute pci_slot_attr_cur_speed = | ||
| 121 | __ATTR(cur_bus_speed, (S_IFREG | S_IRUGO), cur_speed_read_file, NULL); | ||
| 69 | 122 | ||
| 70 | static struct attribute *pci_slot_default_attrs[] = { | 123 | static struct attribute *pci_slot_default_attrs[] = { |
| 71 | &pci_slot_attr_address.attr, | 124 | &pci_slot_attr_address.attr, |
| 125 | &pci_slot_attr_max_speed.attr, | ||
| 126 | &pci_slot_attr_cur_speed.attr, | ||
| 72 | NULL, | 127 | NULL, |
| 73 | }; | 128 | }; |
| 74 | 129 | ||
