diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 8cc6a89130b5..d79d2ee4ac69 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1246,9 +1246,11 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) * initialize. * * If the device is below a Root Port with Configuration RRS - * Software Visibility enabled, reading the Vendor ID returns a + * Software Visibility enabled, reading the Vendor ID may return a * special data value if the device responded with RRS. Read the - * Vendor ID until we get non-RRS status. + * Vendor ID until we get non-RRS status and something other than + * ~0. The Vendor ID of VFs reads ~0, so check their Command + * register instead. * * If there's no Root Port or Configuration RRS Software Visibility * is not enabled, the device may still respond with RRS, but @@ -1268,8 +1270,13 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) if (root && root->config_rrs_sv) { pci_read_config_dword(dev, PCI_VENDOR_ID, &id); - if (!pci_bus_rrs_vendor_id(id)) - break; + if (!pci_bus_rrs_vendor_id(id)) { + if (PCI_POSSIBLE_ERROR(id) && dev->is_virtfn) + pci_read_config_dword(dev, PCI_COMMAND, + &id); + if (!PCI_POSSIBLE_ERROR(id)) + break; + } } else { pci_read_config_dword(dev, PCI_COMMAND, &id); if (!PCI_POSSIBLE_ERROR(id)) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 677cd8797d19..1aa87a3ef9ed 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -5634,6 +5634,18 @@ static void quirk_no_flr_snet(struct pci_dev *dev) } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SOLIDRUN, 0x1000, quirk_no_flr_snet); +/* Some Samsung SSDs advertise Immediate Readiness but aren't ready after FLR */ +static void quirk_no_imm_ready(struct pci_dev *dev) +{ + if (!dev->imm_ready) + return; + + pci_info(dev, "Ignoring incorrectly advertised Immediate Readiness support\n"); + dev->imm_ready = 0; +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SAMSUNG, 0xa80c, quirk_no_imm_ready); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SAMSUNG, 0xa80d, quirk_no_imm_ready); + static void quirk_no_ext_tags(struct pci_dev *pdev) { struct pci_host_bridge *bridge = pci_find_host_bridge(pdev->bus);