forked from Minki/linux
Merge branch 'remotes/lorenzo/pci/controller-fixes'
- Restore R-Car PCIe link early in resume (Kazufumi Ikeda) - Fix Hyper-V PCI ejection memory leak (Dexuan Cui) - Cleanup Hyper-V PCI slots on module unload (Dexuan Cui) - Cleanup Hyper-V PCI slot on device removal to address a race (Dexuan Cui) * remotes/lorenzo/pci/controller-fixes: PCI: hv: Add pci_destroy_slot() in pci_devices_present_work(), if necessary PCI: hv: Add hv_pci_remove_slots() when we unload the driver PCI: hv: Fix a memory leak in hv_eject_device_work() PCI: rcar: Add the initialization of PCIe link in resume_noirq()
This commit is contained in:
commit
4014eb8b61
@ -1486,6 +1486,21 @@ static void hv_pci_assign_slots(struct hv_pcibus_device *hbus)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove entries in sysfs pci slot directory.
|
||||
*/
|
||||
static void hv_pci_remove_slots(struct hv_pcibus_device *hbus)
|
||||
{
|
||||
struct hv_pci_dev *hpdev;
|
||||
|
||||
list_for_each_entry(hpdev, &hbus->children, list_entry) {
|
||||
if (!hpdev->pci_slot)
|
||||
continue;
|
||||
pci_destroy_slot(hpdev->pci_slot);
|
||||
hpdev->pci_slot = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create_root_hv_pci_bus() - Expose a new root PCI bus
|
||||
* @hbus: Root PCI bus, as understood by this driver
|
||||
@ -1761,6 +1776,10 @@ static void pci_devices_present_work(struct work_struct *work)
|
||||
hpdev = list_first_entry(&removed, struct hv_pci_dev,
|
||||
list_entry);
|
||||
list_del(&hpdev->list_entry);
|
||||
|
||||
if (hpdev->pci_slot)
|
||||
pci_destroy_slot(hpdev->pci_slot);
|
||||
|
||||
put_pcichild(hpdev);
|
||||
}
|
||||
|
||||
@ -1900,6 +1919,9 @@ static void hv_eject_device_work(struct work_struct *work)
|
||||
sizeof(*ejct_pkt), (unsigned long)&ctxt.pkt,
|
||||
VM_PKT_DATA_INBAND, 0);
|
||||
|
||||
/* For the get_pcichild() in hv_pci_eject_device() */
|
||||
put_pcichild(hpdev);
|
||||
/* For the two refs got in new_pcichild_device() */
|
||||
put_pcichild(hpdev);
|
||||
put_pcichild(hpdev);
|
||||
put_hvpcibus(hpdev->hbus);
|
||||
@ -2677,6 +2699,7 @@ static int hv_pci_remove(struct hv_device *hdev)
|
||||
pci_lock_rescan_remove();
|
||||
pci_stop_root_bus(hbus->pci_bus);
|
||||
pci_remove_root_bus(hbus->pci_bus);
|
||||
hv_pci_remove_slots(hbus);
|
||||
pci_unlock_rescan_remove();
|
||||
hbus->state = hv_pcibus_removed;
|
||||
}
|
||||
|
@ -46,6 +46,7 @@
|
||||
|
||||
/* Transfer control */
|
||||
#define PCIETCTLR 0x02000
|
||||
#define DL_DOWN BIT(3)
|
||||
#define CFINIT 1
|
||||
#define PCIETSTR 0x02004
|
||||
#define DATA_LINK_ACTIVE 1
|
||||
@ -94,6 +95,7 @@
|
||||
#define MACCTLR 0x011058
|
||||
#define SPEED_CHANGE BIT(24)
|
||||
#define SCRAMBLE_DISABLE BIT(27)
|
||||
#define PMSR 0x01105c
|
||||
#define MACS2R 0x011078
|
||||
#define MACCGSPSETR 0x011084
|
||||
#define SPCNGRSN BIT(31)
|
||||
@ -1130,6 +1132,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
|
||||
pcie = pci_host_bridge_priv(bridge);
|
||||
|
||||
pcie->dev = dev;
|
||||
platform_set_drvdata(pdev, pcie);
|
||||
|
||||
err = pci_parse_request_of_pci_ranges(dev, &pcie->resources, NULL);
|
||||
if (err)
|
||||
@ -1221,10 +1224,28 @@ err_free_bridge:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rcar_pcie_resume_noirq(struct device *dev)
|
||||
{
|
||||
struct rcar_pcie *pcie = dev_get_drvdata(dev);
|
||||
|
||||
if (rcar_pci_read_reg(pcie, PMSR) &&
|
||||
!(rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN))
|
||||
return 0;
|
||||
|
||||
/* Re-establish the PCIe link */
|
||||
rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
|
||||
return rcar_pcie_wait_for_dl(pcie);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops rcar_pcie_pm_ops = {
|
||||
.resume_noirq = rcar_pcie_resume_noirq,
|
||||
};
|
||||
|
||||
static struct platform_driver rcar_pcie_driver = {
|
||||
.driver = {
|
||||
.name = "rcar-pcie",
|
||||
.of_match_table = rcar_pcie_of_match,
|
||||
.pm = &rcar_pcie_pm_ops,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = rcar_pcie_probe,
|
||||
|
Loading…
Reference in New Issue
Block a user