mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-27 22:53:55 +08:00
PCI/PME: Add pcie_walk_rcec() to RCEC PME handling
Root Complex Event Collectors (RCEC) appear as peers of Root Ports and also have the PME capability. As with AER, there is a need to be able to walk the RCiEPs associated with their RCEC for purposes of acting upon them with callbacks. Add RCEC support through the use of pcie_walk_rcec() to the current PME service driver and attach the PME service driver to the RCEC device. Co-developed-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com> Link: https://lore.kernel.org/r/20201121001036.8560-15-sean.v.kelley@intel.com Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> # non-native/no RCEC Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com> Signed-off-by: Sean V Kelley <sean.v.kelley@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
This commit is contained in:
parent
af113553d9
commit
9a2f604f44
@ -310,7 +310,10 @@ static int pcie_pme_can_wakeup(struct pci_dev *dev, void *ign)
|
||||
static void pcie_pme_mark_devices(struct pci_dev *port)
|
||||
{
|
||||
pcie_pme_can_wakeup(port, NULL);
|
||||
if (port->subordinate)
|
||||
|
||||
if (pci_pcie_type(port) == PCI_EXP_TYPE_RC_EC)
|
||||
pcie_walk_rcec(port, pcie_pme_can_wakeup, NULL);
|
||||
else if (port->subordinate)
|
||||
pci_walk_bus(port->subordinate, pcie_pme_can_wakeup, NULL);
|
||||
}
|
||||
|
||||
@ -320,10 +323,16 @@ static void pcie_pme_mark_devices(struct pci_dev *port)
|
||||
*/
|
||||
static int pcie_pme_probe(struct pcie_device *srv)
|
||||
{
|
||||
struct pci_dev *port;
|
||||
struct pci_dev *port = srv->port;
|
||||
struct pcie_pme_service_data *data;
|
||||
int type = pci_pcie_type(port);
|
||||
int ret;
|
||||
|
||||
/* Limit to Root Ports or Root Complex Event Collectors */
|
||||
if (type != PCI_EXP_TYPE_RC_EC &&
|
||||
type != PCI_EXP_TYPE_ROOT_PORT)
|
||||
return -ENODEV;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
@ -333,7 +342,6 @@ static int pcie_pme_probe(struct pcie_device *srv)
|
||||
data->srv = srv;
|
||||
set_service_data(srv, data);
|
||||
|
||||
port = srv->port;
|
||||
pcie_pme_interrupt_enable(port, false);
|
||||
pcie_clear_root_pme_status(port);
|
||||
|
||||
@ -445,7 +453,7 @@ static void pcie_pme_remove(struct pcie_device *srv)
|
||||
|
||||
static struct pcie_port_service_driver pcie_pme_driver = {
|
||||
.name = "pcie_pme",
|
||||
.port_type = PCI_EXP_TYPE_ROOT_PORT,
|
||||
.port_type = PCIE_ANY_PORT,
|
||||
.service = PCIE_PORT_SERVICE_PME,
|
||||
|
||||
.probe = pcie_pme_probe,
|
||||
|
@ -233,12 +233,9 @@ static int get_port_device_capability(struct pci_dev *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Root ports are capable of generating PME too. Root Complex
|
||||
* Event Collectors can also generate PMEs, but we don't handle
|
||||
* those yet.
|
||||
*/
|
||||
if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT &&
|
||||
/* Root Ports and Root Complex Event Collectors may generate PMEs */
|
||||
if ((pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT ||
|
||||
pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC) &&
|
||||
(pcie_ports_native || host->native_pme)) {
|
||||
services |= PCIE_PORT_SERVICE_PME;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user