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

Commit b9c3b266 authored by Dexuan Cui's avatar Dexuan Cui Committed by Jesse Barnes
Browse files

PCI: support device-specific reset methods



Add a new type of quirk for resetting devices at pci_dev_reset time.
This is necessary to handle device with nonstandard reset procedures,
especially useful for guest drivers.

Signed-off-by: default avatarYu Zhao <yu.zhao@intel.com>
Signed-off-by: default avatarDexuan Cui <dexuan.cui@intel.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 2820f333
Loading
Loading
Loading
Loading
+19 −0
Original line number Original line Diff line number Diff line
@@ -2284,6 +2284,21 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe)
	return 0;
	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)
static int pci_dev_reset(struct pci_dev *dev, int probe)
{
{
	int rc;
	int rc;
@@ -2296,6 +2311,10 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)
		down(&dev->dev.sem);
		down(&dev->dev.sem);
	}
	}


	rc = pci_dev_specific_reset(dev, probe);
	if (rc != -ENOTTY)
		goto done;

	rc = pcie_flr(dev, probe);
	rc = pcie_flr(dev, probe);
	if (rc != -ENOTTY)
	if (rc != -ENOTTY)
		goto done;
		goto done;
+8 −0
Original line number Original line Diff line number Diff line
@@ -313,4 +313,12 @@ static inline int pci_resource_alignment(struct pci_dev *dev,


extern void pci_enable_acs(struct pci_dev *dev);
extern void pci_enable_acs(struct pci_dev *dev);


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 */
#endif /* DRIVERS_PCI_H */
+9 −0
Original line number Original line Diff line number Diff line
@@ -2636,6 +2636,15 @@ static int __init pci_apply_final_quirks(void)
}
}


fs_initcall_sync(pci_apply_final_quirks);
fs_initcall_sync(pci_apply_final_quirks);

/*
 * 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
#else
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {}
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {}
#endif
#endif