diff options
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 171 |
1 files changed, 103 insertions, 68 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 206c834d263a..84c757ba0664 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -392,6 +392,14 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
392 | if (state > PCI_D3hot) | 392 | if (state > PCI_D3hot) |
393 | state = PCI_D3hot; | 393 | state = PCI_D3hot; |
394 | 394 | ||
395 | /* | ||
396 | * If the device or the parent bridge can't support PCI PM, ignore | ||
397 | * the request if we're doing anything besides putting it into D0 | ||
398 | * (which would only happen on boot). | ||
399 | */ | ||
400 | if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev)) | ||
401 | return 0; | ||
402 | |||
395 | /* Validate current state: | 403 | /* Validate current state: |
396 | * Can enter D0 from any state, but if we can only go deeper | 404 | * Can enter D0 from any state, but if we can only go deeper |
397 | * to sleep if we're already in a low power state | 405 | * to sleep if we're already in a low power state |
@@ -403,13 +411,6 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
403 | } else if (dev->current_state == state) | 411 | } else if (dev->current_state == state) |
404 | return 0; /* we're already there */ | 412 | return 0; /* we're already there */ |
405 | 413 | ||
406 | /* | ||
407 | * If the device or the parent bridge can't support PCI PM, ignore | ||
408 | * the request if we're doing anything besides putting it into D0 | ||
409 | * (which would only happen on boot). | ||
410 | */ | ||
411 | if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev)) | ||
412 | return 0; | ||
413 | 414 | ||
414 | /* find PCI PM capability in list */ | 415 | /* find PCI PM capability in list */ |
415 | pm = pci_find_capability(dev, PCI_CAP_ID_PM); | 416 | pm = pci_find_capability(dev, PCI_CAP_ID_PM); |
@@ -633,8 +634,6 @@ pci_save_state(struct pci_dev *dev) | |||
633 | pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]); | 634 | pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]); |
634 | if ((i = pci_save_msi_state(dev)) != 0) | 635 | if ((i = pci_save_msi_state(dev)) != 0) |
635 | return i; | 636 | return i; |
636 | if ((i = pci_save_msix_state(dev)) != 0) | ||
637 | return i; | ||
638 | if ((i = pci_save_pcie_state(dev)) != 0) | 637 | if ((i = pci_save_pcie_state(dev)) != 0) |
639 | return i; | 638 | return i; |
640 | if ((i = pci_save_pcix_state(dev)) != 0) | 639 | if ((i = pci_save_pcix_state(dev)) != 0) |
@@ -672,22 +671,11 @@ pci_restore_state(struct pci_dev *dev) | |||
672 | } | 671 | } |
673 | pci_restore_pcix_state(dev); | 672 | pci_restore_pcix_state(dev); |
674 | pci_restore_msi_state(dev); | 673 | pci_restore_msi_state(dev); |
675 | pci_restore_msix_state(dev); | 674 | |
676 | return 0; | 675 | return 0; |
677 | } | 676 | } |
678 | 677 | ||
679 | /** | 678 | static int do_pci_enable_device(struct pci_dev *dev, int bars) |
680 | * pci_enable_device_bars - Initialize some of a device for use | ||
681 | * @dev: PCI device to be initialized | ||
682 | * @bars: bitmask of BAR's that must be configured | ||
683 | * | ||
684 | * Initialize device before it's used by a driver. Ask low-level code | ||
685 | * to enable selected I/O and memory resources. Wake up the device if it | ||
686 | * was suspended. Beware, this function can fail. | ||
687 | */ | ||
688 | |||
689 | int | ||
690 | pci_enable_device_bars(struct pci_dev *dev, int bars) | ||
691 | { | 679 | { |
692 | int err; | 680 | int err; |
693 | 681 | ||
@@ -697,30 +685,47 @@ pci_enable_device_bars(struct pci_dev *dev, int bars) | |||
697 | err = pcibios_enable_device(dev, bars); | 685 | err = pcibios_enable_device(dev, bars); |
698 | if (err < 0) | 686 | if (err < 0) |
699 | return err; | 687 | return err; |
688 | pci_fixup_device(pci_fixup_enable, dev); | ||
689 | |||
700 | return 0; | 690 | return 0; |
701 | } | 691 | } |
702 | 692 | ||
703 | /** | 693 | /** |
704 | * __pci_enable_device - Initialize device before it's used by a driver. | 694 | * __pci_reenable_device - Resume abandoned device |
695 | * @dev: PCI device to be resumed | ||
696 | * | ||
697 | * Note this function is a backend of pci_default_resume and is not supposed | ||
698 | * to be called by normal code, write proper resume handler and use it instead. | ||
699 | */ | ||
700 | int | ||
701 | __pci_reenable_device(struct pci_dev *dev) | ||
702 | { | ||
703 | if (atomic_read(&dev->enable_cnt)) | ||
704 | return do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1); | ||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | /** | ||
709 | * pci_enable_device_bars - Initialize some of a device for use | ||
705 | * @dev: PCI device to be initialized | 710 | * @dev: PCI device to be initialized |
711 | * @bars: bitmask of BAR's that must be configured | ||
706 | * | 712 | * |
707 | * Initialize device before it's used by a driver. Ask low-level code | 713 | * Initialize device before it's used by a driver. Ask low-level code |
708 | * to enable I/O and memory. Wake up the device if it was suspended. | 714 | * to enable selected I/O and memory resources. Wake up the device if it |
709 | * Beware, this function can fail. | 715 | * was suspended. Beware, this function can fail. |
710 | * | ||
711 | * Note this function is a backend and is not supposed to be called by | ||
712 | * normal code, use pci_enable_device() instead. | ||
713 | */ | 716 | */ |
714 | int | 717 | int |
715 | __pci_enable_device(struct pci_dev *dev) | 718 | pci_enable_device_bars(struct pci_dev *dev, int bars) |
716 | { | 719 | { |
717 | int err; | 720 | int err; |
718 | 721 | ||
719 | err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); | 722 | if (atomic_add_return(1, &dev->enable_cnt) > 1) |
720 | if (err) | 723 | return 0; /* already enabled */ |
721 | return err; | 724 | |
722 | pci_fixup_device(pci_fixup_enable, dev); | 725 | err = do_pci_enable_device(dev, bars); |
723 | return 0; | 726 | if (err < 0) |
727 | atomic_dec(&dev->enable_cnt); | ||
728 | return err; | ||
724 | } | 729 | } |
725 | 730 | ||
726 | /** | 731 | /** |
@@ -736,13 +741,7 @@ __pci_enable_device(struct pci_dev *dev) | |||
736 | */ | 741 | */ |
737 | int pci_enable_device(struct pci_dev *dev) | 742 | int pci_enable_device(struct pci_dev *dev) |
738 | { | 743 | { |
739 | int result; | 744 | return pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); |
740 | if (atomic_add_return(1, &dev->enable_cnt) > 1) | ||
741 | return 0; /* already enabled */ | ||
742 | result = __pci_enable_device(dev); | ||
743 | if (result < 0) | ||
744 | atomic_dec(&dev->enable_cnt); | ||
745 | return result; | ||
746 | } | 745 | } |
747 | 746 | ||
748 | /** | 747 | /** |
@@ -921,6 +920,47 @@ err_out: | |||
921 | return -EBUSY; | 920 | return -EBUSY; |
922 | } | 921 | } |
923 | 922 | ||
923 | /** | ||
924 | * pci_release_selected_regions - Release selected PCI I/O and memory resources | ||
925 | * @pdev: PCI device whose resources were previously reserved | ||
926 | * @bars: Bitmask of BARs to be released | ||
927 | * | ||
928 | * Release selected PCI I/O and memory resources previously reserved. | ||
929 | * Call this function only after all use of the PCI regions has ceased. | ||
930 | */ | ||
931 | void pci_release_selected_regions(struct pci_dev *pdev, int bars) | ||
932 | { | ||
933 | int i; | ||
934 | |||
935 | for (i = 0; i < 6; i++) | ||
936 | if (bars & (1 << i)) | ||
937 | pci_release_region(pdev, i); | ||
938 | } | ||
939 | |||
940 | /** | ||
941 | * pci_request_selected_regions - Reserve selected PCI I/O and memory resources | ||
942 | * @pdev: PCI device whose resources are to be reserved | ||
943 | * @bars: Bitmask of BARs to be requested | ||
944 | * @res_name: Name to be associated with resource | ||
945 | */ | ||
946 | int pci_request_selected_regions(struct pci_dev *pdev, int bars, | ||
947 | const char *res_name) | ||
948 | { | ||
949 | int i; | ||
950 | |||
951 | for (i = 0; i < 6; i++) | ||
952 | if (bars & (1 << i)) | ||
953 | if(pci_request_region(pdev, i, res_name)) | ||
954 | goto err_out; | ||
955 | return 0; | ||
956 | |||
957 | err_out: | ||
958 | while(--i >= 0) | ||
959 | if (bars & (1 << i)) | ||
960 | pci_release_region(pdev, i); | ||
961 | |||
962 | return -EBUSY; | ||
963 | } | ||
924 | 964 | ||
925 | /** | 965 | /** |
926 | * pci_release_regions - Release reserved PCI I/O and memory resources | 966 | * pci_release_regions - Release reserved PCI I/O and memory resources |
@@ -933,10 +973,7 @@ err_out: | |||
933 | 973 | ||
934 | void pci_release_regions(struct pci_dev *pdev) | 974 | void pci_release_regions(struct pci_dev *pdev) |
935 | { | 975 | { |
936 | int i; | 976 | pci_release_selected_regions(pdev, (1 << 6) - 1); |
937 | |||
938 | for (i = 0; i < 6; i++) | ||
939 | pci_release_region(pdev, i); | ||
940 | } | 977 | } |
941 | 978 | ||
942 | /** | 979 | /** |
@@ -954,18 +991,7 @@ void pci_release_regions(struct pci_dev *pdev) | |||
954 | */ | 991 | */ |
955 | int pci_request_regions(struct pci_dev *pdev, const char *res_name) | 992 | int pci_request_regions(struct pci_dev *pdev, const char *res_name) |
956 | { | 993 | { |
957 | int i; | 994 | return pci_request_selected_regions(pdev, ((1 << 6) - 1), res_name); |
958 | |||
959 | for (i = 0; i < 6; i++) | ||
960 | if(pci_request_region(pdev, i, res_name)) | ||
961 | goto err_out; | ||
962 | return 0; | ||
963 | |||
964 | err_out: | ||
965 | while(--i >= 0) | ||
966 | pci_release_region(pdev, i); | ||
967 | |||
968 | return -EBUSY; | ||
969 | } | 995 | } |
970 | 996 | ||
971 | /** | 997 | /** |
@@ -1148,7 +1174,23 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) | |||
1148 | return 0; | 1174 | return 0; |
1149 | } | 1175 | } |
1150 | #endif | 1176 | #endif |
1151 | 1177 | ||
1178 | /** | ||
1179 | * pci_select_bars - Make BAR mask from the type of resource | ||
1180 | * @pdev: the PCI device for which BAR mask is made | ||
1181 | * @flags: resource type mask to be selected | ||
1182 | * | ||
1183 | * This helper routine makes bar mask from the type of resource. | ||
1184 | */ | ||
1185 | int pci_select_bars(struct pci_dev *dev, unsigned long flags) | ||
1186 | { | ||
1187 | int i, bars = 0; | ||
1188 | for (i = 0; i < PCI_NUM_RESOURCES; i++) | ||
1189 | if (pci_resource_flags(dev, i) & flags) | ||
1190 | bars |= (1 << i); | ||
1191 | return bars; | ||
1192 | } | ||
1193 | |||
1152 | static int __devinit pci_init(void) | 1194 | static int __devinit pci_init(void) |
1153 | { | 1195 | { |
1154 | struct pci_dev *dev = NULL; | 1196 | struct pci_dev *dev = NULL; |
@@ -1181,12 +1223,6 @@ early_param("pci", pci_setup); | |||
1181 | 1223 | ||
1182 | device_initcall(pci_init); | 1224 | device_initcall(pci_init); |
1183 | 1225 | ||
1184 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) | ||
1185 | /* FIXME: Some boxes have multiple ISA bridges! */ | ||
1186 | struct pci_dev *isa_bridge; | ||
1187 | EXPORT_SYMBOL(isa_bridge); | ||
1188 | #endif | ||
1189 | |||
1190 | EXPORT_SYMBOL_GPL(pci_restore_bars); | 1226 | EXPORT_SYMBOL_GPL(pci_restore_bars); |
1191 | EXPORT_SYMBOL(pci_enable_device_bars); | 1227 | EXPORT_SYMBOL(pci_enable_device_bars); |
1192 | EXPORT_SYMBOL(pci_enable_device); | 1228 | EXPORT_SYMBOL(pci_enable_device); |
@@ -1197,6 +1233,8 @@ EXPORT_SYMBOL(pci_release_regions); | |||
1197 | EXPORT_SYMBOL(pci_request_regions); | 1233 | EXPORT_SYMBOL(pci_request_regions); |
1198 | EXPORT_SYMBOL(pci_release_region); | 1234 | EXPORT_SYMBOL(pci_release_region); |
1199 | EXPORT_SYMBOL(pci_request_region); | 1235 | EXPORT_SYMBOL(pci_request_region); |
1236 | EXPORT_SYMBOL(pci_release_selected_regions); | ||
1237 | EXPORT_SYMBOL(pci_request_selected_regions); | ||
1200 | EXPORT_SYMBOL(pci_set_master); | 1238 | EXPORT_SYMBOL(pci_set_master); |
1201 | EXPORT_SYMBOL(pci_set_mwi); | 1239 | EXPORT_SYMBOL(pci_set_mwi); |
1202 | EXPORT_SYMBOL(pci_clear_mwi); | 1240 | EXPORT_SYMBOL(pci_clear_mwi); |
@@ -1205,13 +1243,10 @@ EXPORT_SYMBOL(pci_set_dma_mask); | |||
1205 | EXPORT_SYMBOL(pci_set_consistent_dma_mask); | 1243 | EXPORT_SYMBOL(pci_set_consistent_dma_mask); |
1206 | EXPORT_SYMBOL(pci_assign_resource); | 1244 | EXPORT_SYMBOL(pci_assign_resource); |
1207 | EXPORT_SYMBOL(pci_find_parent_resource); | 1245 | EXPORT_SYMBOL(pci_find_parent_resource); |
1246 | EXPORT_SYMBOL(pci_select_bars); | ||
1208 | 1247 | ||
1209 | EXPORT_SYMBOL(pci_set_power_state); | 1248 | EXPORT_SYMBOL(pci_set_power_state); |
1210 | EXPORT_SYMBOL(pci_save_state); | 1249 | EXPORT_SYMBOL(pci_save_state); |
1211 | EXPORT_SYMBOL(pci_restore_state); | 1250 | EXPORT_SYMBOL(pci_restore_state); |
1212 | EXPORT_SYMBOL(pci_enable_wake); | 1251 | EXPORT_SYMBOL(pci_enable_wake); |
1213 | 1252 | ||
1214 | /* Quirk info */ | ||
1215 | |||
1216 | EXPORT_SYMBOL(isa_dma_bridge_buggy); | ||
1217 | EXPORT_SYMBOL(pci_pci_problems); | ||