diff options
author | Alex Williamson <alex.williamson@redhat.com> | 2013-12-17 18:43:39 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2013-12-17 19:36:38 -0500 |
commit | 157e876ffe0b28821a0d82d8ac944fe7363bbe87 (patch) | |
tree | 60f443e2745b8b419ece22040d54f619895c465b | |
parent | 6ce4eac1f600b34f2f7f58f9cd8f0503d79e42ae (diff) |
PCI: Add pci_wait_for_pending() (refactor pci_wait_for_pending_transaction())
We currently have two instance of this loop which waits for a pending bit
to clear in a status dword. Generalize the function for future users.
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r-- | drivers/pci/pci.c | 54 | ||||
-rw-r--r-- | include/linux/pci.h | 1 |
2 files changed, 32 insertions, 23 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 33120d156668..bb257b975a8f 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -431,6 +431,32 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res) | |||
431 | } | 431 | } |
432 | 432 | ||
433 | /** | 433 | /** |
434 | * pci_wait_for_pending - wait for @mask bit(s) to clear in status word @pos | ||
435 | * @dev: the PCI device to operate on | ||
436 | * @pos: config space offset of status word | ||
437 | * @mask: mask of bit(s) to care about in status word | ||
438 | * | ||
439 | * Return 1 when mask bit(s) in status word clear, 0 otherwise. | ||
440 | */ | ||
441 | int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask) | ||
442 | { | ||
443 | int i; | ||
444 | |||
445 | /* Wait for Transaction Pending bit clean */ | ||
446 | for (i = 0; i < 4; i++) { | ||
447 | u16 status; | ||
448 | if (i) | ||
449 | msleep((1 << (i - 1)) * 100); | ||
450 | |||
451 | pci_read_config_word(dev, pos, &status); | ||
452 | if (!(status & mask)) | ||
453 | return 1; | ||
454 | } | ||
455 | |||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | /** | ||
434 | * pci_restore_bars - restore a devices BAR values (e.g. after wake-up) | 460 | * pci_restore_bars - restore a devices BAR values (e.g. after wake-up) |
435 | * @dev: PCI device to have its BARs restored | 461 | * @dev: PCI device to have its BARs restored |
436 | * | 462 | * |
@@ -3204,20 +3230,10 @@ EXPORT_SYMBOL(pci_set_dma_seg_boundary); | |||
3204 | */ | 3230 | */ |
3205 | int pci_wait_for_pending_transaction(struct pci_dev *dev) | 3231 | int pci_wait_for_pending_transaction(struct pci_dev *dev) |
3206 | { | 3232 | { |
3207 | int i; | 3233 | if (!pci_is_pcie(dev)) |
3208 | u16 status; | 3234 | return 1; |
3209 | |||
3210 | /* Wait for Transaction Pending bit clean */ | ||
3211 | for (i = 0; i < 4; i++) { | ||
3212 | if (i) | ||
3213 | msleep((1 << (i - 1)) * 100); | ||
3214 | |||
3215 | pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status); | ||
3216 | if (!(status & PCI_EXP_DEVSTA_TRPND)) | ||
3217 | return 1; | ||
3218 | } | ||
3219 | 3235 | ||
3220 | return 0; | 3236 | return pci_wait_for_pending(dev, PCI_EXP_DEVSTA, PCI_EXP_DEVSTA_TRPND); |
3221 | } | 3237 | } |
3222 | EXPORT_SYMBOL(pci_wait_for_pending_transaction); | 3238 | EXPORT_SYMBOL(pci_wait_for_pending_transaction); |
3223 | 3239 | ||
@@ -3244,10 +3260,8 @@ static int pcie_flr(struct pci_dev *dev, int probe) | |||
3244 | 3260 | ||
3245 | static int pci_af_flr(struct pci_dev *dev, int probe) | 3261 | static int pci_af_flr(struct pci_dev *dev, int probe) |
3246 | { | 3262 | { |
3247 | int i; | ||
3248 | int pos; | 3263 | int pos; |
3249 | u8 cap; | 3264 | u8 cap; |
3250 | u8 status; | ||
3251 | 3265 | ||
3252 | pos = pci_find_capability(dev, PCI_CAP_ID_AF); | 3266 | pos = pci_find_capability(dev, PCI_CAP_ID_AF); |
3253 | if (!pos) | 3267 | if (!pos) |
@@ -3261,14 +3275,8 @@ static int pci_af_flr(struct pci_dev *dev, int probe) | |||
3261 | return 0; | 3275 | return 0; |
3262 | 3276 | ||
3263 | /* Wait for Transaction Pending bit clean */ | 3277 | /* Wait for Transaction Pending bit clean */ |
3264 | for (i = 0; i < 4; i++) { | 3278 | if (pci_wait_for_pending(dev, PCI_AF_STATUS, PCI_AF_STATUS_TP)) |
3265 | if (i) | 3279 | goto clear; |
3266 | msleep((1 << (i - 1)) * 100); | ||
3267 | |||
3268 | pci_read_config_byte(dev, pos + PCI_AF_STATUS, &status); | ||
3269 | if (!(status & PCI_AF_STATUS_TP)) | ||
3270 | goto clear; | ||
3271 | } | ||
3272 | 3280 | ||
3273 | dev_err(&dev->dev, "transaction is not cleared; " | 3281 | dev_err(&dev->dev, "transaction is not cleared; " |
3274 | "proceeding with reset anyway\n"); | 3282 | "proceeding with reset anyway\n"); |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 1084a15175e0..211ce43ba483 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -938,6 +938,7 @@ bool pci_check_and_unmask_intx(struct pci_dev *dev); | |||
938 | void pci_msi_off(struct pci_dev *dev); | 938 | void pci_msi_off(struct pci_dev *dev); |
939 | int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size); | 939 | int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size); |
940 | int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask); | 940 | int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask); |
941 | int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask); | ||
941 | int pci_wait_for_pending_transaction(struct pci_dev *dev); | 942 | int pci_wait_for_pending_transaction(struct pci_dev *dev); |
942 | int pcix_get_max_mmrbc(struct pci_dev *dev); | 943 | int pcix_get_max_mmrbc(struct pci_dev *dev); |
943 | int pcix_get_mmrbc(struct pci_dev *dev); | 944 | int pcix_get_mmrbc(struct pci_dev *dev); |