aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2013-12-17 18:43:39 -0500
committerBjorn Helgaas <bhelgaas@google.com>2013-12-17 19:36:38 -0500
commit157e876ffe0b28821a0d82d8ac944fe7363bbe87 (patch)
tree60f443e2745b8b419ece22040d54f619895c465b
parent6ce4eac1f600b34f2f7f58f9cd8f0503d79e42ae (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.c54
-rw-r--r--include/linux/pci.h1
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 */
441int 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 */
3205int pci_wait_for_pending_transaction(struct pci_dev *dev) 3231int 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}
3222EXPORT_SYMBOL(pci_wait_for_pending_transaction); 3238EXPORT_SYMBOL(pci_wait_for_pending_transaction);
3223 3239
@@ -3244,10 +3260,8 @@ static int pcie_flr(struct pci_dev *dev, int probe)
3244 3260
3245static int pci_af_flr(struct pci_dev *dev, int probe) 3261static 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);
938void pci_msi_off(struct pci_dev *dev); 938void pci_msi_off(struct pci_dev *dev);
939int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size); 939int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size);
940int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask); 940int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask);
941int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask);
941int pci_wait_for_pending_transaction(struct pci_dev *dev); 942int pci_wait_for_pending_transaction(struct pci_dev *dev);
942int pcix_get_max_mmrbc(struct pci_dev *dev); 943int pcix_get_max_mmrbc(struct pci_dev *dev);
943int pcix_get_mmrbc(struct pci_dev *dev); 944int pcix_get_mmrbc(struct pci_dev *dev);