Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ca88797 authored by Sheng Yang's avatar Sheng Yang Committed by Jesse Barnes
Browse files

PCI: Extend pci_reset_function() to support PCI Advanced Features



Some PCI devices implement PCI Advanced Features, which means they
support Function Level Reset(FLR).  Implement support for that in
pci_reset_function.

Signed-off-by: default avatarSheng Yang <sheng@linux.intel.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent f7b7baae
Loading
Loading
Loading
Loading
+41 −0
Original line number Original line Diff line number Diff line
@@ -1789,6 +1789,43 @@ static int __pcie_flr(struct pci_dev *dev, int probe)
	return 0;
	return 0;
}
}


static int __pci_af_flr(struct pci_dev *dev, int probe)
{
	int cappos = pci_find_capability(dev, PCI_CAP_ID_AF);
	u8 status;
	u8 cap;

	if (!cappos)
		return -ENOTTY;
	pci_read_config_byte(dev, cappos + PCI_AF_CAP, &cap);
	if (!(cap & PCI_AF_CAP_TP) || !(cap & PCI_AF_CAP_FLR))
		return -ENOTTY;

	if (probe)
		return 0;

	pci_block_user_cfg_access(dev);

	/* Wait for Transaction Pending bit clean */
	msleep(100);
	pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status);
	if (status & PCI_AF_STATUS_TP) {
		dev_info(&dev->dev, "Busy after 100ms while trying to"
				" reset; sleeping for 1 second\n");
		ssleep(1);
		pci_read_config_byte(dev,
				cappos + PCI_AF_STATUS, &status);
		if (status & PCI_AF_STATUS_TP)
			dev_info(&dev->dev, "Still busy after 1s; "
					"proceeding with reset anyway\n");
	}
	pci_write_config_byte(dev, cappos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
	mdelay(100);

	pci_unblock_user_cfg_access(dev);
	return 0;
}

static int __pci_reset_function(struct pci_dev *pdev, int probe)
static int __pci_reset_function(struct pci_dev *pdev, int probe)
{
{
	int res;
	int res;
@@ -1797,6 +1834,10 @@ static int __pci_reset_function(struct pci_dev *pdev, int probe)
	if (res != -ENOTTY)
	if (res != -ENOTTY)
		return res;
		return res;


	res = __pci_af_flr(pdev, probe);
	if (res != -ENOTTY)
		return res;

	return res;
	return res;
}
}