mirror of https://gitee.com/openkylin/linux.git
pci-v4.13-fixes-2
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJZjMwWAAoJEFmIoMA60/r8wIAQAK7w2Gp77O6fcy449UpkIrxe 9NnkiFtAgHy4IZgEchwpATYw2+kpLHKnOebmzdQmQcKWH1TiZ4SUW79sn7wMraYG x7+yFSV8myRuznHlarEaxoitH9hDUzR1mE9xXwa1cs4bwPsmEZrrQyQXQyr8M8mR WvkQkQL2/70c0ue42yTCUxK4ZDhi0R4GpbE3Hul6wdMT0eaSw2f7GEw96ruxPGWG 8/ao0R2evueJRaxaY8sd9Nj1jtlfuLXoY/KIEb/i43nSq6FPyWS9It3wJy6zjM5t uQJZvWnH/ON8FuEeut+0Pqq3voeXrmsEtB3oP37Hh5v4qz5Ge3rTje18oc4/tVmN vR4tekwkI992VMvhyOXaogSHPhVAy6Ykc60UbQO4W5F9H+Z8yE1TgKv2+ss/SU9r NHdEBN9XvrNk4kPXbiXfSylt4bPElszRka3mmj4NGA3QOKSKIQeLBburmr2ExSxN SgTIzf9SpTREJinHKxwsCHa3ahceTsBnzznBtgKEsrbHy2rwmg1FWcUBXONDfEeI uKv3ycFf+ErG2MD5akUxT044tl9Zi3nrZXna0viWzxKIWOCyYCr+lOzGxG0yQth9 W2LT/UJpqAE8PQUXYH0ALpLGXY+ZSbHqb/NpYS87KqiTneeSNsjfxZAfjcjgvI31 BEvXbgndYIOWRjsle9SN =ih3D -----END PGP SIGNATURE----- Merge tag 'pci-v4.13-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci Pull PCI fix from Bjorn Helgaas: "Work around Renesas uPD72020x 32-bit DMA issue" * tag 'pci-v4.13-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: xhci: Reset Renesas uPD72020x USB controller for 32-bit DMA issue PCI: Add pci_reset_function_locked()
This commit is contained in:
commit
4e082e9ba7
|
@ -4259,6 +4259,41 @@ int pci_reset_function(struct pci_dev *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(pci_reset_function);
|
||||
|
||||
/**
|
||||
* pci_reset_function_locked - quiesce and reset a PCI device function
|
||||
* @dev: PCI device to reset
|
||||
*
|
||||
* Some devices allow an individual function to be reset without affecting
|
||||
* other functions in the same device. The PCI device must be responsive
|
||||
* to PCI config space in order to use this function.
|
||||
*
|
||||
* This function does not just reset the PCI portion of a device, but
|
||||
* clears all the state associated with the device. This function differs
|
||||
* from __pci_reset_function() in that it saves and restores device state
|
||||
* over the reset. It also differs from pci_reset_function() in that it
|
||||
* requires the PCI device lock to be held.
|
||||
*
|
||||
* Returns 0 if the device function was successfully reset or negative if the
|
||||
* device doesn't support resetting a single function.
|
||||
*/
|
||||
int pci_reset_function_locked(struct pci_dev *dev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = pci_probe_reset_function(dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
pci_dev_save_and_disable(dev);
|
||||
|
||||
rc = __pci_reset_function_locked(dev);
|
||||
|
||||
pci_dev_restore(dev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_reset_function_locked);
|
||||
|
||||
/**
|
||||
* pci_try_reset_function - quiesce and reset a PCI device function
|
||||
* @dev: PCI device to reset
|
||||
|
|
|
@ -1150,3 +1150,23 @@ static void quirk_usb_early_handoff(struct pci_dev *pdev)
|
|||
}
|
||||
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
|
||||
PCI_CLASS_SERIAL_USB, 8, quirk_usb_early_handoff);
|
||||
|
||||
bool usb_xhci_needs_pci_reset(struct pci_dev *pdev)
|
||||
{
|
||||
/*
|
||||
* Our dear uPD72020{1,2} friend only partially resets when
|
||||
* asked to via the XHCI interface, and may end up doing DMA
|
||||
* at the wrong addresses, as it keeps the top 32bit of some
|
||||
* addresses from its previous programming under obscure
|
||||
* circumstances.
|
||||
* Give it a good wack at probe time. Unfortunately, this
|
||||
* needs to happen before we've had a chance to discover any
|
||||
* quirk, or the system will be in a rather bad state.
|
||||
*/
|
||||
if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
|
||||
(pdev->device == 0x0014 || pdev->device == 0x0015))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_xhci_needs_pci_reset);
|
||||
|
|
|
@ -15,6 +15,7 @@ void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev);
|
|||
void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
|
||||
void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
|
||||
void sb800_prefetch(struct device *dev, int on);
|
||||
bool usb_xhci_needs_pci_reset(struct pci_dev *pdev);
|
||||
#else
|
||||
struct pci_dev;
|
||||
static inline void usb_amd_quirk_pll_disable(void) {}
|
||||
|
|
|
@ -284,6 +284,13 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
|
||||
driver = (struct hc_driver *)id->driver_data;
|
||||
|
||||
/* For some HW implementation, a XHCI reset is just not enough... */
|
||||
if (usb_xhci_needs_pci_reset(dev)) {
|
||||
dev_info(&dev->dev, "Resetting\n");
|
||||
if (pci_reset_function_locked(dev))
|
||||
dev_warn(&dev->dev, "Reset failed");
|
||||
}
|
||||
|
||||
/* Prevent runtime suspending between USB-2 and USB-3 initialization */
|
||||
pm_runtime_get_noresume(&dev->dev);
|
||||
|
||||
|
|
|
@ -1067,6 +1067,7 @@ void pcie_flr(struct pci_dev *dev);
|
|||
int __pci_reset_function(struct pci_dev *dev);
|
||||
int __pci_reset_function_locked(struct pci_dev *dev);
|
||||
int pci_reset_function(struct pci_dev *dev);
|
||||
int pci_reset_function_locked(struct pci_dev *dev);
|
||||
int pci_try_reset_function(struct pci_dev *dev);
|
||||
int pci_probe_reset_slot(struct pci_slot *slot);
|
||||
int pci_reset_slot(struct pci_slot *slot);
|
||||
|
|
Loading…
Reference in New Issue