| Submitter | Dexuan Cui |
|---|---|
| Date | 2009-11-06 09:24:55 |
| Message ID | <1257499497-9186-1-git-send-email-dexuan.cui@intel.com> |
| Download | mbox | patch |
| Permalink | /patch/58023/ |
| State | New |
| Headers | show |
Comments
On Fri, Nov 06, 2009 at 05:24:55PM +0800, Dexuan Cui wrote: > 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 */ Why do it this way instead of having a ->reset method in struct pci_driver?
Matthew Wilcox wrote: > On Fri, Nov 06, 2009 at 05:24:55PM +0800, Dexuan Cui wrote: >> 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 */ > > Why do it this way instead of having a ->reset method in struct > pci_driver? Sorry for the late reply as I was on an accidental leave. Hi Matthew, Currently pci_reset_function() is mainly used by kvm_vm_ioctl_assign_device() and kvm_free_assigned_device(). In the case of KVM VT-d, in host the driver of the device assigned to HVM guest is not the "genuine" one -- it should always be the dummy driver "pci-stub" or NULL, because the "genuine" driver in HVM guest would control the device and in host we should not load an actual driver for the device. So adding a 'reset' field into struct pci_driver doesn't sound like a good idea to me. And the existing pci_dev_reset() has been there for quite a while, so I think adding pci_dev_specific_reset() into pci_dev_reset() should be good. Thanks, -- Dexuan -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Jesse, May I also have your comment? Thanks, -- Dexuan -----Original Message----- From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-owner@vger.kernel.org] On Behalf Of Cui, Dexuan Sent: Tuesday, November 10, 2009 6:15 PM To: Matthew Wilcox Cc: linux-pci@vger.kernel.org Subject: RE: [PATCH 1/3] PCI: support device-specific reset methods. Matthew Wilcox wrote: > On Fri, Nov 06, 2009 at 05:24:55PM +0800, Dexuan Cui wrote: >> 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 */ > > Why do it this way instead of having a ->reset method in struct > pci_driver? Sorry for the late reply as I was on an accidental leave. Hi Matthew, Currently pci_reset_function() is mainly used by kvm_vm_ioctl_assign_device() and kvm_free_assigned_device(). In the case of KVM VT-d, in host the driver of the device assigned to HVM guest is not the "genuine" one -- it should always be the dummy driver "pci-stub" or NULL, because the "genuine" driver in HVM guest would control the device and in host we should not load an actual driver for the device. So adding a 'reset' field into struct pci_driver doesn't sound like a good idea to me. And the existing pci_dev_reset() has been there for quite a while, so I think adding pci_dev_specific_reset() into pci_dev_reset() should be good. Thanks, -- Dexuan -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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