Commit 4014eb8b authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

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()
parents 83d82352 340d4556
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -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;
	}
+21 −0
Original line number Diff line number Diff line
@@ -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,