forked from mirrors/linux
		
	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>
This commit is contained in:
		
							parent
							
								
									6ce4eac1f6
								
							
						
					
					
						commit
						157e876ffe
					
				
					 2 changed files with 32 additions and 23 deletions
				
			
		| 
						 | 
					@ -430,6 +430,32 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
 | 
				
			||||||
	return best;
 | 
						return best;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * pci_wait_for_pending - wait for @mask bit(s) to clear in status word @pos
 | 
				
			||||||
 | 
					 * @dev: the PCI device to operate on
 | 
				
			||||||
 | 
					 * @pos: config space offset of status word
 | 
				
			||||||
 | 
					 * @mask: mask of bit(s) to care about in status word
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return 1 when mask bit(s) in status word clear, 0 otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Wait for Transaction Pending bit clean */
 | 
				
			||||||
 | 
						for (i = 0; i < 4; i++) {
 | 
				
			||||||
 | 
							u16 status;
 | 
				
			||||||
 | 
							if (i)
 | 
				
			||||||
 | 
								msleep((1 << (i - 1)) * 100);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pci_read_config_word(dev, pos, &status);
 | 
				
			||||||
 | 
							if (!(status & mask))
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * pci_restore_bars - restore a devices BAR values (e.g. after wake-up)
 | 
					 * pci_restore_bars - restore a devices BAR values (e.g. after wake-up)
 | 
				
			||||||
 * @dev: PCI device to have its BARs restored
 | 
					 * @dev: PCI device to have its BARs restored
 | 
				
			||||||
| 
						 | 
					@ -3204,20 +3230,10 @@ EXPORT_SYMBOL(pci_set_dma_seg_boundary);
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int pci_wait_for_pending_transaction(struct pci_dev *dev)
 | 
					int pci_wait_for_pending_transaction(struct pci_dev *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						if (!pci_is_pcie(dev))
 | 
				
			||||||
	u16 status;
 | 
							return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Wait for Transaction Pending bit clean */
 | 
						return pci_wait_for_pending(dev, PCI_EXP_DEVSTA, PCI_EXP_DEVSTA_TRPND);
 | 
				
			||||||
	for (i = 0; i < 4; i++) {
 | 
					 | 
				
			||||||
		if (i)
 | 
					 | 
				
			||||||
			msleep((1 << (i - 1)) * 100);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status);
 | 
					 | 
				
			||||||
		if (!(status & PCI_EXP_DEVSTA_TRPND))
 | 
					 | 
				
			||||||
			return 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(pci_wait_for_pending_transaction);
 | 
					EXPORT_SYMBOL(pci_wait_for_pending_transaction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3244,10 +3260,8 @@ static int pcie_flr(struct pci_dev *dev, int probe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int pci_af_flr(struct pci_dev *dev, int probe)
 | 
					static int pci_af_flr(struct pci_dev *dev, int probe)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
	int pos;
 | 
						int pos;
 | 
				
			||||||
	u8 cap;
 | 
						u8 cap;
 | 
				
			||||||
	u8 status;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pos = pci_find_capability(dev, PCI_CAP_ID_AF);
 | 
						pos = pci_find_capability(dev, PCI_CAP_ID_AF);
 | 
				
			||||||
	if (!pos)
 | 
						if (!pos)
 | 
				
			||||||
| 
						 | 
					@ -3261,14 +3275,8 @@ static int pci_af_flr(struct pci_dev *dev, int probe)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Wait for Transaction Pending bit clean */
 | 
						/* Wait for Transaction Pending bit clean */
 | 
				
			||||||
	for (i = 0; i < 4; i++) {
 | 
						if (pci_wait_for_pending(dev, PCI_AF_STATUS, PCI_AF_STATUS_TP))
 | 
				
			||||||
		if (i)
 | 
							goto clear;
 | 
				
			||||||
			msleep((1 << (i - 1)) * 100);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		pci_read_config_byte(dev, pos + PCI_AF_STATUS, &status);
 | 
					 | 
				
			||||||
		if (!(status & PCI_AF_STATUS_TP))
 | 
					 | 
				
			||||||
			goto clear;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_err(&dev->dev, "transaction is not cleared; "
 | 
						dev_err(&dev->dev, "transaction is not cleared; "
 | 
				
			||||||
			"proceeding with reset anyway\n");
 | 
								"proceeding with reset anyway\n");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -938,6 +938,7 @@ bool pci_check_and_unmask_intx(struct pci_dev *dev);
 | 
				
			||||||
void pci_msi_off(struct pci_dev *dev);
 | 
					void pci_msi_off(struct pci_dev *dev);
 | 
				
			||||||
int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size);
 | 
					int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size);
 | 
				
			||||||
int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask);
 | 
					int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask);
 | 
				
			||||||
 | 
					int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask);
 | 
				
			||||||
int pci_wait_for_pending_transaction(struct pci_dev *dev);
 | 
					int pci_wait_for_pending_transaction(struct pci_dev *dev);
 | 
				
			||||||
int pcix_get_max_mmrbc(struct pci_dev *dev);
 | 
					int pcix_get_max_mmrbc(struct pci_dev *dev);
 | 
				
			||||||
int pcix_get_mmrbc(struct pci_dev *dev);
 | 
					int pcix_get_mmrbc(struct pci_dev *dev);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue