diff options
-rw-r--r-- | drivers/pci/pci.c | 80 | ||||
-rw-r--r-- | include/linux/pci.h | 3 |
2 files changed, 66 insertions, 17 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 287b685aaa5c..599978631a46 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -921,6 +921,47 @@ err_out: | |||
921 | return -EBUSY; | 921 | return -EBUSY; |
922 | } | 922 | } |
923 | 923 | ||
924 | /** | ||
925 | * pci_release_selected_regions - Release selected PCI I/O and memory resources | ||
926 | * @pdev: PCI device whose resources were previously reserved | ||
927 | * @bars: Bitmask of BARs to be released | ||
928 | * | ||
929 | * Release selected PCI I/O and memory resources previously reserved. | ||
930 | * Call this function only after all use of the PCI regions has ceased. | ||
931 | */ | ||
932 | void pci_release_selected_regions(struct pci_dev *pdev, int bars) | ||
933 | { | ||
934 | int i; | ||
935 | |||
936 | for (i = 0; i < 6; i++) | ||
937 | if (bars & (1 << i)) | ||
938 | pci_release_region(pdev, i); | ||
939 | } | ||
940 | |||
941 | /** | ||
942 | * pci_request_selected_regions - Reserve selected PCI I/O and memory resources | ||
943 | * @pdev: PCI device whose resources are to be reserved | ||
944 | * @bars: Bitmask of BARs to be requested | ||
945 | * @res_name: Name to be associated with resource | ||
946 | */ | ||
947 | int pci_request_selected_regions(struct pci_dev *pdev, int bars, | ||
948 | const char *res_name) | ||
949 | { | ||
950 | int i; | ||
951 | |||
952 | for (i = 0; i < 6; i++) | ||
953 | if (bars & (1 << i)) | ||
954 | if(pci_request_region(pdev, i, res_name)) | ||
955 | goto err_out; | ||
956 | return 0; | ||
957 | |||
958 | err_out: | ||
959 | while(--i >= 0) | ||
960 | if (bars & (1 << i)) | ||
961 | pci_release_region(pdev, i); | ||
962 | |||
963 | return -EBUSY; | ||
964 | } | ||
924 | 965 | ||
925 | /** | 966 | /** |
926 | * pci_release_regions - Release reserved PCI I/O and memory resources | 967 | * pci_release_regions - Release reserved PCI I/O and memory resources |
@@ -933,10 +974,7 @@ err_out: | |||
933 | 974 | ||
934 | void pci_release_regions(struct pci_dev *pdev) | 975 | void pci_release_regions(struct pci_dev *pdev) |
935 | { | 976 | { |
936 | int i; | 977 | pci_release_selected_regions(pdev, (1 << 6) - 1); |
937 | |||
938 | for (i = 0; i < 6; i++) | ||
939 | pci_release_region(pdev, i); | ||
940 | } | 978 | } |
941 | 979 | ||
942 | /** | 980 | /** |
@@ -954,18 +992,7 @@ void pci_release_regions(struct pci_dev *pdev) | |||
954 | */ | 992 | */ |
955 | int pci_request_regions(struct pci_dev *pdev, const char *res_name) | 993 | int pci_request_regions(struct pci_dev *pdev, const char *res_name) |
956 | { | 994 | { |
957 | int i; | 995 | 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 | } | 996 | } |
970 | 997 | ||
971 | /** | 998 | /** |
@@ -1148,7 +1175,23 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) | |||
1148 | return 0; | 1175 | return 0; |
1149 | } | 1176 | } |
1150 | #endif | 1177 | #endif |
1151 | 1178 | ||
1179 | /** | ||
1180 | * pci_select_bars - Make BAR mask from the type of resource | ||
1181 | * @pdev: the PCI device for which BAR mask is made | ||
1182 | * @flags: resource type mask to be selected | ||
1183 | * | ||
1184 | * This helper routine makes bar mask from the type of resource. | ||
1185 | */ | ||
1186 | int pci_select_bars(struct pci_dev *dev, unsigned long flags) | ||
1187 | { | ||
1188 | int i, bars = 0; | ||
1189 | for (i = 0; i < PCI_NUM_RESOURCES; i++) | ||
1190 | if (pci_resource_flags(dev, i) & flags) | ||
1191 | bars |= (1 << i); | ||
1192 | return bars; | ||
1193 | } | ||
1194 | |||
1152 | static int __devinit pci_init(void) | 1195 | static int __devinit pci_init(void) |
1153 | { | 1196 | { |
1154 | struct pci_dev *dev = NULL; | 1197 | struct pci_dev *dev = NULL; |
@@ -1197,6 +1240,8 @@ EXPORT_SYMBOL(pci_release_regions); | |||
1197 | EXPORT_SYMBOL(pci_request_regions); | 1240 | EXPORT_SYMBOL(pci_request_regions); |
1198 | EXPORT_SYMBOL(pci_release_region); | 1241 | EXPORT_SYMBOL(pci_release_region); |
1199 | EXPORT_SYMBOL(pci_request_region); | 1242 | EXPORT_SYMBOL(pci_request_region); |
1243 | EXPORT_SYMBOL(pci_release_selected_regions); | ||
1244 | EXPORT_SYMBOL(pci_request_selected_regions); | ||
1200 | EXPORT_SYMBOL(pci_set_master); | 1245 | EXPORT_SYMBOL(pci_set_master); |
1201 | EXPORT_SYMBOL(pci_set_mwi); | 1246 | EXPORT_SYMBOL(pci_set_mwi); |
1202 | EXPORT_SYMBOL(pci_clear_mwi); | 1247 | EXPORT_SYMBOL(pci_clear_mwi); |
@@ -1205,6 +1250,7 @@ EXPORT_SYMBOL(pci_set_dma_mask); | |||
1205 | EXPORT_SYMBOL(pci_set_consistent_dma_mask); | 1250 | EXPORT_SYMBOL(pci_set_consistent_dma_mask); |
1206 | EXPORT_SYMBOL(pci_assign_resource); | 1251 | EXPORT_SYMBOL(pci_assign_resource); |
1207 | EXPORT_SYMBOL(pci_find_parent_resource); | 1252 | EXPORT_SYMBOL(pci_find_parent_resource); |
1253 | EXPORT_SYMBOL(pci_select_bars); | ||
1208 | 1254 | ||
1209 | EXPORT_SYMBOL(pci_set_power_state); | 1255 | EXPORT_SYMBOL(pci_set_power_state); |
1210 | EXPORT_SYMBOL(pci_save_state); | 1256 | EXPORT_SYMBOL(pci_save_state); |
diff --git a/include/linux/pci.h b/include/linux/pci.h index f3c617eabd8d..df875626b71a 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -533,6 +533,7 @@ void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno); | |||
533 | int __must_check pci_assign_resource(struct pci_dev *dev, int i); | 533 | int __must_check pci_assign_resource(struct pci_dev *dev, int i); |
534 | int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i); | 534 | int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i); |
535 | void pci_restore_bars(struct pci_dev *dev); | 535 | void pci_restore_bars(struct pci_dev *dev); |
536 | int pci_select_bars(struct pci_dev *dev, unsigned long flags); | ||
536 | 537 | ||
537 | /* ROM control related routines */ | 538 | /* ROM control related routines */ |
538 | void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size); | 539 | void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size); |
@@ -561,6 +562,8 @@ int __must_check pci_request_regions(struct pci_dev *, const char *); | |||
561 | void pci_release_regions(struct pci_dev *); | 562 | void pci_release_regions(struct pci_dev *); |
562 | int __must_check pci_request_region(struct pci_dev *, int, const char *); | 563 | int __must_check pci_request_region(struct pci_dev *, int, const char *); |
563 | void pci_release_region(struct pci_dev *, int); | 564 | void pci_release_region(struct pci_dev *, int); |
565 | int pci_request_selected_regions(struct pci_dev *, int, const char *); | ||
566 | void pci_release_selected_regions(struct pci_dev *, int); | ||
564 | 567 | ||
565 | /* drivers/pci/bus.c */ | 568 | /* drivers/pci/bus.c */ |
566 | int __must_check pci_bus_alloc_resource(struct pci_bus *bus, | 569 | int __must_check pci_bus_alloc_resource(struct pci_bus *bus, |