Merge branch 'pci/reset'
- Add pci_reset_bus_function() Secondary Bus Reset interface (Raphael Norwitz) - Work around Huawei Intelligent NIC VF FLR erratum (Chiqijun) * pci/reset: PCI: Work around Huawei Intelligent NIC VF FLR erratum PCI: Add pci_reset_bus_function() Secondary Bus Reset interface
This commit is contained in:
commit
76d826c32f
@ -5020,6 +5020,16 @@ static int pci_dev_reset_slot_function(struct pci_dev *dev, int probe)
|
||||
return pci_reset_hotplug_slot(dev->slot->hotplug, probe);
|
||||
}
|
||||
|
||||
static int pci_reset_bus_function(struct pci_dev *dev, int probe)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = pci_dev_reset_slot_function(dev, probe);
|
||||
if (rc != -ENOTTY)
|
||||
return rc;
|
||||
return pci_parent_bus_reset(dev, probe);
|
||||
}
|
||||
|
||||
static void pci_dev_lock(struct pci_dev *dev)
|
||||
{
|
||||
pci_cfg_access_lock(dev);
|
||||
@ -5140,10 +5150,7 @@ int __pci_reset_function_locked(struct pci_dev *dev)
|
||||
rc = pci_pm_reset(dev, 0);
|
||||
if (rc != -ENOTTY)
|
||||
return rc;
|
||||
rc = pci_dev_reset_slot_function(dev, 0);
|
||||
if (rc != -ENOTTY)
|
||||
return rc;
|
||||
return pci_parent_bus_reset(dev, 0);
|
||||
return pci_reset_bus_function(dev, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__pci_reset_function_locked);
|
||||
|
||||
@ -5173,13 +5180,10 @@ int pci_probe_reset_function(struct pci_dev *dev)
|
||||
if (rc != -ENOTTY)
|
||||
return rc;
|
||||
rc = pci_pm_reset(dev, 1);
|
||||
if (rc != -ENOTTY)
|
||||
return rc;
|
||||
rc = pci_dev_reset_slot_function(dev, 1);
|
||||
if (rc != -ENOTTY)
|
||||
return rc;
|
||||
|
||||
return pci_parent_bus_reset(dev, 1);
|
||||
return pci_reset_bus_function(dev, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3912,6 +3912,69 @@ static int delay_250ms_after_flr(struct pci_dev *dev, int probe)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PCI_DEVICE_ID_HINIC_VF 0x375E
|
||||
#define HINIC_VF_FLR_TYPE 0x1000
|
||||
#define HINIC_VF_FLR_CAP_BIT (1UL << 30)
|
||||
#define HINIC_VF_OP 0xE80
|
||||
#define HINIC_VF_FLR_PROC_BIT (1UL << 18)
|
||||
#define HINIC_OPERATION_TIMEOUT 15000 /* 15 seconds */
|
||||
|
||||
/* Device-specific reset method for Huawei Intelligent NIC virtual functions */
|
||||
static int reset_hinic_vf_dev(struct pci_dev *pdev, int probe)
|
||||
{
|
||||
unsigned long timeout;
|
||||
void __iomem *bar;
|
||||
u32 val;
|
||||
|
||||
if (probe)
|
||||
return 0;
|
||||
|
||||
bar = pci_iomap(pdev, 0, 0);
|
||||
if (!bar)
|
||||
return -ENOTTY;
|
||||
|
||||
/* Get and check firmware capabilities */
|
||||
val = ioread32be(bar + HINIC_VF_FLR_TYPE);
|
||||
if (!(val & HINIC_VF_FLR_CAP_BIT)) {
|
||||
pci_iounmap(pdev, bar);
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/* Set HINIC_VF_FLR_PROC_BIT for the start of FLR */
|
||||
val = ioread32be(bar + HINIC_VF_OP);
|
||||
val = val | HINIC_VF_FLR_PROC_BIT;
|
||||
iowrite32be(val, bar + HINIC_VF_OP);
|
||||
|
||||
pcie_flr(pdev);
|
||||
|
||||
/*
|
||||
* The device must recapture its Bus and Device Numbers after FLR
|
||||
* in order generate Completions. Issue a config write to let the
|
||||
* device capture this information.
|
||||
*/
|
||||
pci_write_config_word(pdev, PCI_VENDOR_ID, 0);
|
||||
|
||||
/* Firmware clears HINIC_VF_FLR_PROC_BIT when reset is complete */
|
||||
timeout = jiffies + msecs_to_jiffies(HINIC_OPERATION_TIMEOUT);
|
||||
do {
|
||||
val = ioread32be(bar + HINIC_VF_OP);
|
||||
if (!(val & HINIC_VF_FLR_PROC_BIT))
|
||||
goto reset_complete;
|
||||
msleep(20);
|
||||
} while (time_before(jiffies, timeout));
|
||||
|
||||
val = ioread32be(bar + HINIC_VF_OP);
|
||||
if (!(val & HINIC_VF_FLR_PROC_BIT))
|
||||
goto reset_complete;
|
||||
|
||||
pci_warn(pdev, "Reset dev timeout, FLR ack reg: %#010x\n", val);
|
||||
|
||||
reset_complete:
|
||||
pci_iounmap(pdev, bar);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
|
||||
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF,
|
||||
reset_intel_82599_sfp_virtfn },
|
||||
@ -3924,6 +3987,8 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
|
||||
{ PCI_VENDOR_ID_INTEL, 0x0a54, delay_250ms_after_flr },
|
||||
{ PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
|
||||
reset_chelsio_generic_dev },
|
||||
{ PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_HINIC_VF,
|
||||
reset_hinic_vf_dev },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user