diff mbox

[1/3] PCI: support device-specific reset methods.

Message ID 1257499497-9186-1-git-send-email-dexuan.cui@intel.com (mailing list archive)
State Superseded, archived
Headers show

Commit Message

Dexuan Cui Nov. 6, 2009, 9:24 a.m. UTC
None
diff mbox

Patch

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 6edecff..b1ae98a 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2224,6 +2224,21 @@  static int pci_parent_bus_reset(struct pci_dev *dev, int probe)
 	return 0;
 }
 
+static int pci_dev_specific_reset(struct pci_dev *dev, int probe)
+{
+	struct pci_dev_reset_methods *i;
+
+	for (i = pci_dev_reset_methods; i->reset; i++) {
+		if ((i->vendor == dev->vendor ||
+		     i->vendor == (u16)PCI_ANY_ID) &&
+		    (i->device == dev->device ||
+		     i->device == (u16)PCI_ANY_ID))
+			return i->reset(dev, probe);
+	}
+
+	return -ENOTTY;
+}
+
 static int pci_dev_reset(struct pci_dev *dev, int probe)
 {
 	int rc;
@@ -2236,6 +2251,10 @@  static int pci_dev_reset(struct pci_dev *dev, int probe)
 		down(&dev->dev.sem);
 	}
 
+	rc = pci_dev_specific_reset(dev, probe);
+	if (rc != -ENOTTY)
+		goto done;
+
 	rc = pcie_flr(dev, probe);
 	if (rc != -ENOTTY)
 		goto done;
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index d92d195..02247ac 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -311,4 +311,12 @@  static inline int pci_resource_alignment(struct pci_dev *dev,
 	return resource_alignment(res);
 }
 
+struct pci_dev_reset_methods {
+	u16 vendor;
+	u16 device;
+	int (*reset)(struct pci_dev *dev, int probe);
+};
+
+extern struct pci_dev_reset_methods pci_dev_reset_methods[];
+
 #endif /* DRIVERS_PCI_H */
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 6099fac..dfc734e 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2572,6 +2572,15 @@  void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
 	}
 	pci_do_fixups(dev, start, end);
 }
+
+/*
+ * Followings are device-specific reset methods which can be used to
+ * reset a single function if other methods (e.g. FLR, PM D0->D3) are
+ * not available.
+ */
+struct pci_dev_reset_methods pci_dev_reset_methods[] = {
+	{ 0 }
+};
 #else
 void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {}
 #endif