Merge branch 'pci/portdrv'
- move pcieport_if.h to drivers/pci/pcie/ to encapsulate it (Frederick Lawler) - merge pcieport_if.h into portdrv.h (Bjorn Helgaas) - move workaround for BIOS PME issue from portdrv to PCI core (Bjorn Helgaas) - completely disable portdrv with "pcie_ports=compat" (Bjorn Helgaas) - remove portdrv link order dependency (Bjorn Helgaas) - remove support for unused VC portdrv service (Bjorn Helgaas) - simplify portdrv feature permission checking (Bjorn Helgaas) - remove "pcie_hp=nomsi" parameter (use "pci=nomsi" instead) (Bjorn Helgaas) - remove unnecessary "pcie_ports=auto" parameter (Bjorn Helgaas) - use cached AER capability offset (Frederick Lawler) - don't enable DPC if BIOS hasn't granted AER control (Mika Westerberg) - rename pcie-dpc.c to dpc.c (Bjorn Helgaas) * pci/portdrv: PCI/DPC: Rename from pcie-dpc.c to dpc.c PCI/DPC: Do not enable DPC if AER control is not allowed by the BIOS PCI/AER: Use cached AER Capability offset PCI/portdrv: Rename and reverse sense of pcie_ports_auto PCI/portdrv: Encapsulate pcie_ports_auto inside the port driver PCI/portdrv: Remove unnecessary "pcie_ports=auto" parameter PCI/portdrv: Remove "pcie_hp=nomsi" kernel parameter PCI/portdrv: Remove unnecessary include of <linux/pci-aspm.h> PCI/portdrv: Simplify PCIe feature permission checking PCI/portdrv: Remove unused PCIE_PORT_SERVICE_VC PCI/portdrv: Remove pcie_port_bus_type link order dependency PCI/portdrv: Disable port driver in compat mode PCI/PM: Clear PCIe PME Status bit for Root Complex Event Collectors PCI/PM: Clear PCIe PME Status bit in core, not PCIe port driver PCI/PM: Move pcie_clear_root_pme_status() to core PCI/portdrv: Merge pcieport_if.h into portdrv.h PCI/portdrv: Move pcieport_if.h to drivers/pci/pcie/ Conflicts: drivers/pci/pcie/Makefile drivers/pci/pcie/portdrv.h
This commit is contained in:
@ -3130,18 +3130,13 @@
|
|||||||
force Enable ASPM even on devices that claim not to support it.
|
force Enable ASPM even on devices that claim not to support it.
|
||||||
WARNING: Forcing ASPM on may cause system lockups.
|
WARNING: Forcing ASPM on may cause system lockups.
|
||||||
|
|
||||||
pcie_hp= [PCIE] PCI Express Hotplug driver options:
|
pcie_ports= [PCIE] PCIe port services handling:
|
||||||
nomsi Do not use MSI for PCI Express Native Hotplug (this
|
native Use native PCIe services (PME, AER, DPC, PCIe hotplug)
|
||||||
makes all PCIe ports use INTx for hotplug services).
|
even if the platform doesn't give the OS permission to
|
||||||
|
use them. This may cause conflicts if the platform
|
||||||
pcie_ports= [PCIE] PCIe ports handling:
|
also tries to use these services.
|
||||||
auto Ask the BIOS whether or not to use native PCIe services
|
compat Disable native PCIe services (PME, AER, DPC, PCIe
|
||||||
associated with PCIe ports (PME, hot-plug, AER). Use
|
hotplug).
|
||||||
them only if that is allowed by the BIOS.
|
|
||||||
native Use native PCIe services associated with PCIe ports
|
|
||||||
unconditionally.
|
|
||||||
compat Treat PCIe ports as PCI-to-PCI bridges, disable the PCIe
|
|
||||||
ports driver.
|
|
||||||
|
|
||||||
pcie_port_pm= [PCIE] PCIe port power management handling:
|
pcie_port_pm= [PCIE] PCIe port power management handling:
|
||||||
off Disable power management of all PCIe ports
|
off Disable power management of all PCIe ports
|
||||||
|
@ -873,6 +873,7 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
|
|||||||
struct acpi_device *device = root->device;
|
struct acpi_device *device = root->device;
|
||||||
int node = acpi_get_node(device->handle);
|
int node = acpi_get_node(device->handle);
|
||||||
struct pci_bus *bus;
|
struct pci_bus *bus;
|
||||||
|
struct pci_host_bridge *host_bridge;
|
||||||
|
|
||||||
info->root = root;
|
info->root = root;
|
||||||
info->bridge = device;
|
info->bridge = device;
|
||||||
@ -897,9 +898,17 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
|
|||||||
if (!bus)
|
if (!bus)
|
||||||
goto out_release_info;
|
goto out_release_info;
|
||||||
|
|
||||||
|
host_bridge = to_pci_host_bridge(bus->bridge);
|
||||||
|
if (!(root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL))
|
||||||
|
host_bridge->native_hotplug = 0;
|
||||||
|
if (!(root->osc_control_set & OSC_PCI_EXPRESS_AER_CONTROL))
|
||||||
|
host_bridge->native_aer = 0;
|
||||||
|
if (!(root->osc_control_set & OSC_PCI_EXPRESS_PME_CONTROL))
|
||||||
|
host_bridge->native_pme = 0;
|
||||||
|
|
||||||
pci_scan_child_bus(bus);
|
pci_scan_child_bus(bus);
|
||||||
pci_set_host_bridge_release(to_pci_host_bridge(bus->bridge),
|
pci_set_host_bridge_release(host_bridge, acpi_pci_root_release_info,
|
||||||
acpi_pci_root_release_info, info);
|
info);
|
||||||
if (node != NUMA_NO_NODE)
|
if (node != NUMA_NO_NODE)
|
||||||
dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node);
|
dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node);
|
||||||
return bus;
|
return bus;
|
||||||
|
@ -20,10 +20,11 @@
|
|||||||
#include <linux/pci_hotplug.h>
|
#include <linux/pci_hotplug.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/sched/signal.h> /* signal_pending() */
|
#include <linux/sched/signal.h> /* signal_pending() */
|
||||||
#include <linux/pcieport_if.h>
|
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
|
|
||||||
|
#include "../pcie/portdrv.h"
|
||||||
|
|
||||||
#define MY_NAME "pciehp"
|
#define MY_NAME "pciehp"
|
||||||
|
|
||||||
extern bool pciehp_poll_mode;
|
extern bool pciehp_poll_mode;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <linux/suspend.h>
|
#include <linux/suspend.h>
|
||||||
#include <linux/kexec.h>
|
#include <linux/kexec.h>
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
|
#include "pcie/portdrv.h"
|
||||||
|
|
||||||
struct pci_dynid {
|
struct pci_dynid {
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
@ -712,6 +713,18 @@ static void pci_pm_complete(struct device *dev)
|
|||||||
#endif /* !CONFIG_PM_SLEEP */
|
#endif /* !CONFIG_PM_SLEEP */
|
||||||
|
|
||||||
#ifdef CONFIG_SUSPEND
|
#ifdef CONFIG_SUSPEND
|
||||||
|
static void pcie_pme_root_status_cleanup(struct pci_dev *pci_dev)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Some BIOSes forget to clear Root PME Status bits after system
|
||||||
|
* wakeup, which breaks ACPI-based runtime wakeup on PCI Express.
|
||||||
|
* Clear those bits now just in case (shouldn't hurt).
|
||||||
|
*/
|
||||||
|
if (pci_is_pcie(pci_dev) &&
|
||||||
|
(pci_pcie_type(pci_dev) == PCI_EXP_TYPE_ROOT_PORT ||
|
||||||
|
pci_pcie_type(pci_dev) == PCI_EXP_TYPE_RC_EC))
|
||||||
|
pcie_clear_root_pme_status(pci_dev);
|
||||||
|
}
|
||||||
|
|
||||||
static int pci_pm_suspend(struct device *dev)
|
static int pci_pm_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
@ -871,6 +884,8 @@ static int pci_pm_resume_noirq(struct device *dev)
|
|||||||
if (pci_has_legacy_pm_support(pci_dev))
|
if (pci_has_legacy_pm_support(pci_dev))
|
||||||
return pci_legacy_resume_early(dev);
|
return pci_legacy_resume_early(dev);
|
||||||
|
|
||||||
|
pcie_pme_root_status_cleanup(pci_dev);
|
||||||
|
|
||||||
if (drv && drv->pm && drv->pm->resume_noirq)
|
if (drv && drv->pm && drv->pm->resume_noirq)
|
||||||
error = drv->pm->resume_noirq(dev);
|
error = drv->pm->resume_noirq(dev);
|
||||||
|
|
||||||
@ -1572,8 +1587,49 @@ struct bus_type pci_bus_type = {
|
|||||||
};
|
};
|
||||||
EXPORT_SYMBOL(pci_bus_type);
|
EXPORT_SYMBOL(pci_bus_type);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PCIEPORTBUS
|
||||||
|
static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
|
||||||
|
{
|
||||||
|
struct pcie_device *pciedev;
|
||||||
|
struct pcie_port_service_driver *driver;
|
||||||
|
|
||||||
|
if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pciedev = to_pcie_device(dev);
|
||||||
|
driver = to_service_driver(drv);
|
||||||
|
|
||||||
|
if (driver->service != pciedev->service)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (driver->port_type != PCIE_ANY_PORT &&
|
||||||
|
driver->port_type != pci_pcie_type(pciedev->port))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bus_type pcie_port_bus_type = {
|
||||||
|
.name = "pci_express",
|
||||||
|
.match = pcie_port_bus_match,
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL_GPL(pcie_port_bus_type);
|
||||||
|
#endif
|
||||||
|
|
||||||
static int __init pci_driver_init(void)
|
static int __init pci_driver_init(void)
|
||||||
{
|
{
|
||||||
return bus_register(&pci_bus_type);
|
int ret;
|
||||||
|
|
||||||
|
ret = bus_register(&pci_bus_type);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
#ifdef CONFIG_PCIEPORTBUS
|
||||||
|
ret = bus_register(&pcie_port_bus_type);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
postcore_initcall(pci_driver_init);
|
postcore_initcall(pci_driver_init);
|
||||||
|
@ -1684,6 +1684,15 @@ int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state);
|
EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pcie_clear_root_pme_status - Clear root port PME interrupt status.
|
||||||
|
* @dev: PCIe root port or event collector.
|
||||||
|
*/
|
||||||
|
void pcie_clear_root_pme_status(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
pcie_capability_set_dword(dev, PCI_EXP_RTSTA, PCI_EXP_RTSTA_PME);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pci_check_pme_status - Check if given device has generated PME.
|
* pci_check_pme_status - Check if given device has generated PME.
|
||||||
* @dev: Device to check.
|
* @dev: Device to check.
|
||||||
|
@ -71,6 +71,7 @@ void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
|
|||||||
void pci_power_up(struct pci_dev *dev);
|
void pci_power_up(struct pci_dev *dev);
|
||||||
void pci_disable_enabled_device(struct pci_dev *dev);
|
void pci_disable_enabled_device(struct pci_dev *dev);
|
||||||
int pci_finish_runtime_suspend(struct pci_dev *dev);
|
int pci_finish_runtime_suspend(struct pci_dev *dev);
|
||||||
|
void pcie_clear_root_pme_status(struct pci_dev *dev);
|
||||||
int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
|
int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
|
||||||
void pci_pme_restore(struct pci_dev *dev);
|
void pci_pme_restore(struct pci_dev *dev);
|
||||||
bool pci_dev_keep_suspended(struct pci_dev *dev);
|
bool pci_dev_keep_suspended(struct pci_dev *dev);
|
||||||
|
@ -2,13 +2,12 @@
|
|||||||
#
|
#
|
||||||
# Makefile for PCI Express features and port driver
|
# Makefile for PCI Express features and port driver
|
||||||
|
|
||||||
pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o
|
pcieportdrv-y := portdrv_core.o portdrv_pci.o
|
||||||
pcieportdrv-$(CONFIG_ACPI) += portdrv_acpi.o
|
|
||||||
|
|
||||||
obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
|
obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
|
||||||
|
|
||||||
obj-$(CONFIG_PCIEASPM) += aspm.o
|
obj-$(CONFIG_PCIEASPM) += aspm.o
|
||||||
obj-$(CONFIG_PCIEAER) += aer/
|
obj-$(CONFIG_PCIEAER) += aer/
|
||||||
obj-$(CONFIG_PCIE_PME) += pme.o
|
obj-$(CONFIG_PCIE_PME) += pme.o
|
||||||
obj-$(CONFIG_PCIE_DPC) += pcie-dpc.o
|
obj-$(CONFIG_PCIE_DPC) += dpc.o
|
||||||
obj-$(CONFIG_PCIE_PTM) += ptm.o
|
obj-$(CONFIG_PCIE_PTM) += ptm.o
|
||||||
|
@ -344,7 +344,7 @@ static int aer_inject(struct aer_error_inj *einj)
|
|||||||
goto out_put;
|
goto out_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
|
pos_cap_err = dev->aer_cap;
|
||||||
if (!pos_cap_err) {
|
if (!pos_cap_err) {
|
||||||
pci_err(dev, "aer_inject: Device doesn't support AER\n");
|
pci_err(dev, "aer_inject: Device doesn't support AER\n");
|
||||||
ret = -EPROTONOSUPPORT;
|
ret = -EPROTONOSUPPORT;
|
||||||
@ -355,7 +355,7 @@ static int aer_inject(struct aer_error_inj *einj)
|
|||||||
pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK,
|
pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK,
|
||||||
&uncor_mask);
|
&uncor_mask);
|
||||||
|
|
||||||
rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR);
|
rp_pos_cap_err = rpdev->aer_cap;
|
||||||
if (!rp_pos_cap_err) {
|
if (!rp_pos_cap_err) {
|
||||||
pci_err(rpdev, "aer_inject: Root port doesn't support AER\n");
|
pci_err(rpdev, "aer_inject: Root port doesn't support AER\n");
|
||||||
ret = -EPROTONOSUPPORT;
|
ret = -EPROTONOSUPPORT;
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/pcieport_if.h>
|
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
#include "aerdrv.h"
|
#include "aerdrv.h"
|
||||||
|
@ -9,10 +9,11 @@
|
|||||||
#define _AERDRV_H_
|
#define _AERDRV_H_
|
||||||
|
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/pcieport_if.h>
|
|
||||||
#include <linux/aer.h>
|
#include <linux/aer.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
|
||||||
|
#include "../portdrv.h"
|
||||||
|
|
||||||
#define SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE| \
|
#define SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE| \
|
||||||
PCI_EXP_RTCTL_SENFEE| \
|
PCI_EXP_RTCTL_SENFEE| \
|
||||||
PCI_EXP_RTCTL_SEFEE)
|
PCI_EXP_RTCTL_SEFEE)
|
||||||
|
@ -40,7 +40,7 @@ static int enable_ecrc_checking(struct pci_dev *dev)
|
|||||||
if (!pci_is_pcie(dev))
|
if (!pci_is_pcie(dev))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
|
pos = dev->aer_cap;
|
||||||
if (!pos)
|
if (!pos)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ static int disable_ecrc_checking(struct pci_dev *dev)
|
|||||||
if (!pci_is_pcie(dev))
|
if (!pci_is_pcie(dev))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
|
pos = dev->aer_cap;
|
||||||
if (!pos)
|
if (!pos)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/pcieport_if.h>
|
|
||||||
|
#include "portdrv.h"
|
||||||
#include "../pci.h"
|
#include "../pci.h"
|
||||||
#include "aer/aerdrv.h"
|
#include "aer/aerdrv.h"
|
||||||
|
|
@ -14,7 +14,6 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/pcieport_if.h>
|
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
|
||||||
#include "../pci.h"
|
#include "../pci.h"
|
||||||
|
@ -11,7 +11,66 @@
|
|||||||
|
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
|
|
||||||
#define PCIE_PORT_DEVICE_MAXSERVICES 5
|
extern bool pcie_ports_native;
|
||||||
|
|
||||||
|
/* Service Type */
|
||||||
|
#define PCIE_PORT_SERVICE_PME_SHIFT 0 /* Power Management Event */
|
||||||
|
#define PCIE_PORT_SERVICE_PME (1 << PCIE_PORT_SERVICE_PME_SHIFT)
|
||||||
|
#define PCIE_PORT_SERVICE_AER_SHIFT 1 /* Advanced Error Reporting */
|
||||||
|
#define PCIE_PORT_SERVICE_AER (1 << PCIE_PORT_SERVICE_AER_SHIFT)
|
||||||
|
#define PCIE_PORT_SERVICE_HP_SHIFT 2 /* Native Hotplug */
|
||||||
|
#define PCIE_PORT_SERVICE_HP (1 << PCIE_PORT_SERVICE_HP_SHIFT)
|
||||||
|
#define PCIE_PORT_SERVICE_DPC_SHIFT 3 /* Downstream Port Containment */
|
||||||
|
#define PCIE_PORT_SERVICE_DPC (1 << PCIE_PORT_SERVICE_DPC_SHIFT)
|
||||||
|
|
||||||
|
#define PCIE_PORT_DEVICE_MAXSERVICES 4
|
||||||
|
|
||||||
|
/* Port Type */
|
||||||
|
#define PCIE_ANY_PORT (~0)
|
||||||
|
|
||||||
|
struct pcie_device {
|
||||||
|
int irq; /* Service IRQ/MSI/MSI-X Vector */
|
||||||
|
struct pci_dev *port; /* Root/Upstream/Downstream Port */
|
||||||
|
u32 service; /* Port service this device represents */
|
||||||
|
void *priv_data; /* Service Private Data */
|
||||||
|
struct device device; /* Generic Device Interface */
|
||||||
|
};
|
||||||
|
#define to_pcie_device(d) container_of(d, struct pcie_device, device)
|
||||||
|
|
||||||
|
static inline void set_service_data(struct pcie_device *dev, void *data)
|
||||||
|
{
|
||||||
|
dev->priv_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *get_service_data(struct pcie_device *dev)
|
||||||
|
{
|
||||||
|
return dev->priv_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pcie_port_service_driver {
|
||||||
|
const char *name;
|
||||||
|
int (*probe) (struct pcie_device *dev);
|
||||||
|
void (*remove) (struct pcie_device *dev);
|
||||||
|
int (*suspend) (struct pcie_device *dev);
|
||||||
|
int (*resume) (struct pcie_device *dev);
|
||||||
|
|
||||||
|
/* Device driver may resume normal operations */
|
||||||
|
void (*error_resume)(struct pci_dev *dev);
|
||||||
|
|
||||||
|
/* Link Reset Capability - AER service driver specific */
|
||||||
|
pci_ers_result_t (*reset_link) (struct pci_dev *dev);
|
||||||
|
|
||||||
|
int port_type; /* Type of the port this driver can handle */
|
||||||
|
u32 service; /* Port service this device represents */
|
||||||
|
|
||||||
|
struct device_driver driver;
|
||||||
|
};
|
||||||
|
#define to_service_driver(d) \
|
||||||
|
container_of(d, struct pcie_port_service_driver, driver)
|
||||||
|
|
||||||
|
int pcie_port_service_register(struct pcie_port_service_driver *new);
|
||||||
|
void pcie_port_service_unregister(struct pcie_port_service_driver *new);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The PCIe Capability Interrupt Message Number (PCIe r3.1, sec 7.8.2) must
|
* The PCIe Capability Interrupt Message Number (PCIe r3.1, sec 7.8.2) must
|
||||||
* be one of the first 32 MSI-X entries. Per PCI r3.0, sec 6.8.3.1, MSI
|
* be one of the first 32 MSI-X entries. Per PCI r3.0, sec 6.8.3.1, MSI
|
||||||
@ -33,20 +92,6 @@ void pcie_port_bus_unregister(void);
|
|||||||
|
|
||||||
struct pci_dev;
|
struct pci_dev;
|
||||||
|
|
||||||
void pcie_clear_root_pme_status(struct pci_dev *dev);
|
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_PCI_PCIE
|
|
||||||
extern bool pciehp_msi_disabled;
|
|
||||||
|
|
||||||
static inline bool pciehp_no_msi(void)
|
|
||||||
{
|
|
||||||
return pciehp_msi_disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* !CONFIG_HOTPLUG_PCI_PCIE */
|
|
||||||
static inline bool pciehp_no_msi(void) { return false; }
|
|
||||||
#endif /* !CONFIG_HOTPLUG_PCI_PCIE */
|
|
||||||
|
|
||||||
#ifdef CONFIG_PCIE_PME
|
#ifdef CONFIG_PCIE_PME
|
||||||
extern bool pcie_pme_msi_disabled;
|
extern bool pcie_pme_msi_disabled;
|
||||||
|
|
||||||
@ -67,15 +112,4 @@ static inline bool pcie_pme_no_msi(void) { return false; }
|
|||||||
static inline void pcie_pme_interrupt_enable(struct pci_dev *dev, bool en) {}
|
static inline void pcie_pme_interrupt_enable(struct pci_dev *dev, bool en) {}
|
||||||
#endif /* !CONFIG_PCIE_PME */
|
#endif /* !CONFIG_PCIE_PME */
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI
|
|
||||||
void pcie_port_acpi_setup(struct pci_dev *port, int *mask);
|
|
||||||
|
|
||||||
static inline void pcie_port_platform_notify(struct pci_dev *port, int *mask)
|
|
||||||
{
|
|
||||||
pcie_port_acpi_setup(port, mask);
|
|
||||||
}
|
|
||||||
#else /* !CONFIG_ACPI */
|
|
||||||
static inline void pcie_port_platform_notify(struct pci_dev *port, int *mask){}
|
|
||||||
#endif /* !CONFIG_ACPI */
|
|
||||||
|
|
||||||
#endif /* _PORTDRV_H_ */
|
#endif /* _PORTDRV_H_ */
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/pci-acpi.h>
|
#include <linux/pci-acpi.h>
|
||||||
#include <linux/pcieport_if.h>
|
|
||||||
|
|
||||||
#include "aer/aerdrv.h"
|
#include "aer/aerdrv.h"
|
||||||
#include "../pci.h"
|
#include "../pci.h"
|
||||||
@ -48,11 +47,11 @@ void pcie_port_acpi_setup(struct pci_dev *port, int *srv_mask)
|
|||||||
|
|
||||||
flags = root->osc_control_set;
|
flags = root->osc_control_set;
|
||||||
|
|
||||||
*srv_mask = PCIE_PORT_SERVICE_VC | PCIE_PORT_SERVICE_DPC;
|
*srv_mask = 0;
|
||||||
if (flags & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL)
|
if (flags & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL)
|
||||||
*srv_mask |= PCIE_PORT_SERVICE_HP;
|
*srv_mask |= PCIE_PORT_SERVICE_HP;
|
||||||
if (flags & OSC_PCI_EXPRESS_PME_CONTROL)
|
if (flags & OSC_PCI_EXPRESS_PME_CONTROL)
|
||||||
*srv_mask |= PCIE_PORT_SERVICE_PME;
|
*srv_mask |= PCIE_PORT_SERVICE_PME;
|
||||||
if (flags & OSC_PCI_EXPRESS_AER_CONTROL)
|
if (flags & OSC_PCI_EXPRESS_AER_CONTROL)
|
||||||
*srv_mask |= PCIE_PORT_SERVICE_AER;
|
*srv_mask |= PCIE_PORT_SERVICE_AER | PCIE_PORT_SERVICE_DPC;
|
||||||
}
|
}
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
|
||||||
/*
|
|
||||||
* File: portdrv_bus.c
|
|
||||||
* Purpose: PCI Express Port Bus Driver's Bus Overloading Functions
|
|
||||||
*
|
|
||||||
* Copyright (C) 2004 Intel
|
|
||||||
* Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/pci.h>
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/errno.h>
|
|
||||||
#include <linux/pm.h>
|
|
||||||
|
|
||||||
#include <linux/pcieport_if.h>
|
|
||||||
#include "portdrv.h"
|
|
||||||
|
|
||||||
static int pcie_port_bus_match(struct device *dev, struct device_driver *drv);
|
|
||||||
|
|
||||||
struct bus_type pcie_port_bus_type = {
|
|
||||||
.name = "pci_express",
|
|
||||||
.match = pcie_port_bus_match,
|
|
||||||
};
|
|
||||||
EXPORT_SYMBOL_GPL(pcie_port_bus_type);
|
|
||||||
|
|
||||||
static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
|
|
||||||
{
|
|
||||||
struct pcie_device *pciedev;
|
|
||||||
struct pcie_port_service_driver *driver;
|
|
||||||
|
|
||||||
if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
pciedev = to_pcie_device(dev);
|
|
||||||
driver = to_service_driver(drv);
|
|
||||||
|
|
||||||
if (driver->service != pciedev->service)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if ((driver->port_type != PCIE_ANY_PORT) &&
|
|
||||||
(driver->port_type != pci_pcie_type(pciedev->port)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pcie_port_bus_register(void)
|
|
||||||
{
|
|
||||||
return bus_register(&pcie_port_bus_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pcie_port_bus_unregister(void)
|
|
||||||
{
|
|
||||||
bus_unregister(&pcie_port_bus_type);
|
|
||||||
}
|
|
@ -14,23 +14,11 @@
|
|||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/pcieport_if.h>
|
|
||||||
#include <linux/aer.h>
|
#include <linux/aer.h>
|
||||||
|
|
||||||
#include "../pci.h"
|
#include "../pci.h"
|
||||||
#include "portdrv.h"
|
#include "portdrv.h"
|
||||||
|
|
||||||
bool pciehp_msi_disabled;
|
|
||||||
|
|
||||||
static int __init pciehp_setup(char *str)
|
|
||||||
{
|
|
||||||
if (!strncmp(str, "nomsi", 5))
|
|
||||||
pciehp_msi_disabled = true;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
__setup("pcie_hp=", pciehp_setup);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* release_pcie_device - free PCI Express port service device structure
|
* release_pcie_device - free PCI Express port service device structure
|
||||||
* @dev: Port service device to release
|
* @dev: Port service device to release
|
||||||
@ -51,7 +39,7 @@ static void release_pcie_device(struct device *dev)
|
|||||||
static int pcie_message_numbers(struct pci_dev *dev, int mask,
|
static int pcie_message_numbers(struct pci_dev *dev, int mask,
|
||||||
u32 *pme, u32 *aer, u32 *dpc)
|
u32 *pme, u32 *aer, u32 *dpc)
|
||||||
{
|
{
|
||||||
u32 nvec = 0, pos, reg32;
|
u32 nvec = 0, pos;
|
||||||
u16 reg16;
|
u16 reg16;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -67,8 +55,11 @@ static int pcie_message_numbers(struct pci_dev *dev, int mask,
|
|||||||
nvec = *pme + 1;
|
nvec = *pme + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PCIEAER
|
||||||
if (mask & PCIE_PORT_SERVICE_AER) {
|
if (mask & PCIE_PORT_SERVICE_AER) {
|
||||||
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
|
u32 reg32;
|
||||||
|
|
||||||
|
pos = dev->aer_cap;
|
||||||
if (pos) {
|
if (pos) {
|
||||||
pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS,
|
pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS,
|
||||||
®32);
|
®32);
|
||||||
@ -76,6 +67,7 @@ static int pcie_message_numbers(struct pci_dev *dev, int mask,
|
|||||||
nvec = max(nvec, *aer + 1);
|
nvec = max(nvec, *aer + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (mask & PCIE_PORT_SERVICE_DPC) {
|
if (mask & PCIE_PORT_SERVICE_DPC) {
|
||||||
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DPC);
|
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DPC);
|
||||||
@ -168,16 +160,13 @@ static int pcie_init_service_irqs(struct pci_dev *dev, int *irqs, int mask)
|
|||||||
irqs[i] = -1;
|
irqs[i] = -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we support PME or hotplug, but we can't use MSI/MSI-X for
|
* If we support PME but can't use MSI/MSI-X for it, we have to
|
||||||
* them, we have to fall back to INTx or other interrupts, e.g., a
|
* fall back to INTx or other interrupts, e.g., a system shared
|
||||||
* system shared interrupt.
|
* interrupt.
|
||||||
*/
|
*/
|
||||||
if ((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi())
|
if ((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi())
|
||||||
goto legacy_irq;
|
goto legacy_irq;
|
||||||
|
|
||||||
if ((mask & PCIE_PORT_SERVICE_HP) && pciehp_no_msi())
|
|
||||||
goto legacy_irq;
|
|
||||||
|
|
||||||
/* Try to use MSI-X or MSI if supported */
|
/* Try to use MSI-X or MSI if supported */
|
||||||
if (pcie_port_enable_irq_vec(dev, irqs, mask) == 0)
|
if (pcie_port_enable_irq_vec(dev, irqs, mask) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
@ -188,10 +177,8 @@ legacy_irq:
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
|
for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++)
|
||||||
if (i != PCIE_PORT_SERVICE_VC_SHIFT)
|
|
||||||
irqs[i] = pci_irq_vector(dev, 0);
|
irqs[i] = pci_irq_vector(dev, 0);
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -208,23 +195,13 @@ legacy_irq:
|
|||||||
*/
|
*/
|
||||||
static int get_port_device_capability(struct pci_dev *dev)
|
static int get_port_device_capability(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
|
struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
|
||||||
int services = 0;
|
int services = 0;
|
||||||
int cap_mask = 0;
|
|
||||||
|
|
||||||
if (pcie_ports_disabled)
|
if (dev->is_hotplug_bridge &&
|
||||||
return 0;
|
(pcie_ports_native || host->native_hotplug)) {
|
||||||
|
|
||||||
cap_mask = PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP
|
|
||||||
| PCIE_PORT_SERVICE_VC;
|
|
||||||
if (pci_aer_available())
|
|
||||||
cap_mask |= PCIE_PORT_SERVICE_AER | PCIE_PORT_SERVICE_DPC;
|
|
||||||
|
|
||||||
if (pcie_ports_auto)
|
|
||||||
pcie_port_platform_notify(dev, &cap_mask);
|
|
||||||
|
|
||||||
/* Hot-Plug Capable */
|
|
||||||
if ((cap_mask & PCIE_PORT_SERVICE_HP) && dev->is_hotplug_bridge) {
|
|
||||||
services |= PCIE_PORT_SERVICE_HP;
|
services |= PCIE_PORT_SERVICE_HP;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable hot-plug interrupts in case they have been enabled
|
* Disable hot-plug interrupts in case they have been enabled
|
||||||
* by the BIOS and the hot-plug service driver is not loaded.
|
* by the BIOS and the hot-plug service driver is not loaded.
|
||||||
@ -232,23 +209,29 @@ static int get_port_device_capability(struct pci_dev *dev)
|
|||||||
pcie_capability_clear_word(dev, PCI_EXP_SLTCTL,
|
pcie_capability_clear_word(dev, PCI_EXP_SLTCTL,
|
||||||
PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE);
|
PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE);
|
||||||
}
|
}
|
||||||
/* AER capable */
|
|
||||||
if ((cap_mask & PCIE_PORT_SERVICE_AER)
|
#ifdef CONFIG_PCIEAER
|
||||||
&& pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) {
|
if (dev->aer_cap && pci_aer_available() &&
|
||||||
|
(pcie_ports_native || host->native_aer)) {
|
||||||
services |= PCIE_PORT_SERVICE_AER;
|
services |= PCIE_PORT_SERVICE_AER;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable AER on this port in case it's been enabled by the
|
* Disable AER on this port in case it's been enabled by the
|
||||||
* BIOS (the AER service driver will enable it when necessary).
|
* BIOS (the AER service driver will enable it when necessary).
|
||||||
*/
|
*/
|
||||||
pci_disable_pcie_error_reporting(dev);
|
pci_disable_pcie_error_reporting(dev);
|
||||||
}
|
}
|
||||||
/* VC support */
|
#endif
|
||||||
if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC))
|
|
||||||
services |= PCIE_PORT_SERVICE_VC;
|
/*
|
||||||
/* Root ports are capable of generating PME too */
|
* Root ports are capable of generating PME too. Root Complex
|
||||||
if ((cap_mask & PCIE_PORT_SERVICE_PME)
|
* Event Collectors can also generate PMEs, but we don't handle
|
||||||
&& pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) {
|
* those yet.
|
||||||
|
*/
|
||||||
|
if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT &&
|
||||||
|
(pcie_ports_native || host->native_pme)) {
|
||||||
services |= PCIE_PORT_SERVICE_PME;
|
services |= PCIE_PORT_SERVICE_PME;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable PME interrupt on this port in case it's been enabled
|
* Disable PME interrupt on this port in case it's been enabled
|
||||||
* by the BIOS (the PME service driver will enable it when
|
* by the BIOS (the PME service driver will enable it when
|
||||||
@ -256,7 +239,9 @@ static int get_port_device_capability(struct pci_dev *dev)
|
|||||||
*/
|
*/
|
||||||
pcie_pme_interrupt_enable(dev, false);
|
pcie_pme_interrupt_enable(dev, false);
|
||||||
}
|
}
|
||||||
if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DPC))
|
|
||||||
|
if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DPC) &&
|
||||||
|
pci_aer_available() && services & PCIE_PORT_SERVICE_AER)
|
||||||
services |= PCIE_PORT_SERVICE_DPC;
|
services |= PCIE_PORT_SERVICE_DPC;
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
@ -334,7 +319,7 @@ int pcie_port_device_register(struct pci_dev *dev)
|
|||||||
*/
|
*/
|
||||||
status = pcie_init_service_irqs(dev, irqs, capabilities);
|
status = pcie_init_service_irqs(dev, irqs, capabilities);
|
||||||
if (status) {
|
if (status) {
|
||||||
capabilities &= PCIE_PORT_SERVICE_VC | PCIE_PORT_SERVICE_HP;
|
capabilities &= PCIE_PORT_SERVICE_HP;
|
||||||
if (!capabilities)
|
if (!capabilities)
|
||||||
goto error_disable;
|
goto error_disable;
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,8 @@
|
|||||||
#include <linux/pm.h>
|
#include <linux/pm.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/pcieport_if.h>
|
|
||||||
#include <linux/aer.h>
|
#include <linux/aer.h>
|
||||||
#include <linux/dmi.h>
|
#include <linux/dmi.h>
|
||||||
#include <linux/pci-aspm.h>
|
|
||||||
|
|
||||||
#include "../pci.h"
|
#include "../pci.h"
|
||||||
#include "portdrv.h"
|
#include "portdrv.h"
|
||||||
@ -25,22 +23,18 @@
|
|||||||
bool pcie_ports_disabled;
|
bool pcie_ports_disabled;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this switch is set, ACPI _OSC will be used to determine whether or not to
|
* If the user specified "pcie_ports=native", use the PCIe services regardless
|
||||||
* enable PCIe port native services.
|
* of whether the platform has given us permission. On ACPI systems, this
|
||||||
|
* means we ignore _OSC.
|
||||||
*/
|
*/
|
||||||
bool pcie_ports_auto = true;
|
bool pcie_ports_native;
|
||||||
|
|
||||||
static int __init pcie_port_setup(char *str)
|
static int __init pcie_port_setup(char *str)
|
||||||
{
|
{
|
||||||
if (!strncmp(str, "compat", 6)) {
|
if (!strncmp(str, "compat", 6))
|
||||||
pcie_ports_disabled = true;
|
pcie_ports_disabled = true;
|
||||||
} else if (!strncmp(str, "native", 6)) {
|
else if (!strncmp(str, "native", 6))
|
||||||
pcie_ports_disabled = false;
|
pcie_ports_native = true;
|
||||||
pcie_ports_auto = false;
|
|
||||||
} else if (!strncmp(str, "auto", 4)) {
|
|
||||||
pcie_ports_disabled = false;
|
|
||||||
pcie_ports_auto = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -48,15 +42,6 @@ __setup("pcie_ports=", pcie_port_setup);
|
|||||||
|
|
||||||
/* global data */
|
/* global data */
|
||||||
|
|
||||||
/**
|
|
||||||
* pcie_clear_root_pme_status - Clear root port PME interrupt status.
|
|
||||||
* @dev: PCIe root port or event collector.
|
|
||||||
*/
|
|
||||||
void pcie_clear_root_pme_status(struct pci_dev *dev)
|
|
||||||
{
|
|
||||||
pcie_capability_set_dword(dev, PCI_EXP_RTSTA, PCI_EXP_RTSTA_PME);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pcie_portdrv_restore_config(struct pci_dev *dev)
|
static int pcie_portdrv_restore_config(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
@ -69,20 +54,6 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
static int pcie_port_resume_noirq(struct device *dev)
|
|
||||||
{
|
|
||||||
struct pci_dev *pdev = to_pci_dev(dev);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Some BIOSes forget to clear Root PME Status bits after system wakeup
|
|
||||||
* which breaks ACPI-based runtime wakeup on PCI Express, so clear those
|
|
||||||
* bits now just in case (shouldn't hurt).
|
|
||||||
*/
|
|
||||||
if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT)
|
|
||||||
pcie_clear_root_pme_status(pdev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pcie_port_runtime_suspend(struct device *dev)
|
static int pcie_port_runtime_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
return to_pci_dev(dev)->bridge_d3 ? 0 : -EBUSY;
|
return to_pci_dev(dev)->bridge_d3 ? 0 : -EBUSY;
|
||||||
@ -110,7 +81,6 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
|
|||||||
.thaw = pcie_port_device_resume,
|
.thaw = pcie_port_device_resume,
|
||||||
.poweroff = pcie_port_device_suspend,
|
.poweroff = pcie_port_device_suspend,
|
||||||
.restore = pcie_port_device_resume,
|
.restore = pcie_port_device_resume,
|
||||||
.resume_noirq = pcie_port_resume_noirq,
|
|
||||||
.runtime_suspend = pcie_port_runtime_suspend,
|
.runtime_suspend = pcie_port_runtime_suspend,
|
||||||
.runtime_resume = pcie_port_runtime_resume,
|
.runtime_resume = pcie_port_runtime_resume,
|
||||||
.runtime_idle = pcie_port_runtime_idle,
|
.runtime_idle = pcie_port_runtime_idle,
|
||||||
@ -281,22 +251,11 @@ static const struct dmi_system_id pcie_portdrv_dmi_table[] __initconst = {
|
|||||||
|
|
||||||
static int __init pcie_portdrv_init(void)
|
static int __init pcie_portdrv_init(void)
|
||||||
{
|
{
|
||||||
int retval;
|
|
||||||
|
|
||||||
if (pcie_ports_disabled)
|
if (pcie_ports_disabled)
|
||||||
return pci_register_driver(&pcie_portdriver);
|
return -EACCES;
|
||||||
|
|
||||||
dmi_check_system(pcie_portdrv_dmi_table);
|
dmi_check_system(pcie_portdrv_dmi_table);
|
||||||
|
|
||||||
retval = pcie_port_bus_register();
|
return pci_register_driver(&pcie_portdriver);
|
||||||
if (retval) {
|
|
||||||
printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
retval = pci_register_driver(&pcie_portdriver);
|
|
||||||
if (retval)
|
|
||||||
pcie_port_bus_unregister();
|
|
||||||
out:
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
device_initcall(pcie_portdrv_init);
|
device_initcall(pcie_portdrv_init);
|
||||||
|
@ -540,6 +540,16 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
|
|||||||
INIT_LIST_HEAD(&bridge->windows);
|
INIT_LIST_HEAD(&bridge->windows);
|
||||||
bridge->dev.release = pci_release_host_bridge_dev;
|
bridge->dev.release = pci_release_host_bridge_dev;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We assume we can manage these PCIe features. Some systems may
|
||||||
|
* reserve these for use by the platform itself, e.g., an ACPI BIOS
|
||||||
|
* may implement its own AER handling and use _OSC to prevent the
|
||||||
|
* OS from interfering.
|
||||||
|
*/
|
||||||
|
bridge->native_aer = 1;
|
||||||
|
bridge->native_hotplug = 1;
|
||||||
|
bridge->native_pme = 1;
|
||||||
|
|
||||||
return bridge;
|
return bridge;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(pci_alloc_host_bridge);
|
EXPORT_SYMBOL(pci_alloc_host_bridge);
|
||||||
|
@ -470,6 +470,9 @@ struct pci_host_bridge {
|
|||||||
struct msi_controller *msi;
|
struct msi_controller *msi;
|
||||||
unsigned int ignore_reset_delay:1; /* For entire hierarchy */
|
unsigned int ignore_reset_delay:1; /* For entire hierarchy */
|
||||||
unsigned int no_ext_tags:1; /* No Extended Tags */
|
unsigned int no_ext_tags:1; /* No Extended Tags */
|
||||||
|
unsigned int native_aer:1; /* OS may use PCIe AER */
|
||||||
|
unsigned int native_hotplug:1; /* OS may use PCIe hotplug */
|
||||||
|
unsigned int native_pme:1; /* OS may use PCIe PME */
|
||||||
/* Resource alignment requirements */
|
/* Resource alignment requirements */
|
||||||
resource_size_t (*align_resource)(struct pci_dev *dev,
|
resource_size_t (*align_resource)(struct pci_dev *dev,
|
||||||
const struct resource *res,
|
const struct resource *res,
|
||||||
@ -1447,10 +1450,8 @@ static inline int pci_irqd_intx_xlate(struct irq_domain *d,
|
|||||||
|
|
||||||
#ifdef CONFIG_PCIEPORTBUS
|
#ifdef CONFIG_PCIEPORTBUS
|
||||||
extern bool pcie_ports_disabled;
|
extern bool pcie_ports_disabled;
|
||||||
extern bool pcie_ports_auto;
|
|
||||||
#else
|
#else
|
||||||
#define pcie_ports_disabled true
|
#define pcie_ports_disabled true
|
||||||
#define pcie_ports_auto false
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PCIEASPM
|
#ifdef CONFIG_PCIEASPM
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
|
||||||
/*
|
|
||||||
* File: pcieport_if.h
|
|
||||||
* Purpose: PCI Express Port Bus Driver's IF Data Structure
|
|
||||||
*
|
|
||||||
* Copyright (C) 2004 Intel
|
|
||||||
* Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _PCIEPORT_IF_H_
|
|
||||||
#define _PCIEPORT_IF_H_
|
|
||||||
|
|
||||||
/* Port Type */
|
|
||||||
#define PCIE_ANY_PORT (~0)
|
|
||||||
|
|
||||||
/* Service Type */
|
|
||||||
#define PCIE_PORT_SERVICE_PME_SHIFT 0 /* Power Management Event */
|
|
||||||
#define PCIE_PORT_SERVICE_PME (1 << PCIE_PORT_SERVICE_PME_SHIFT)
|
|
||||||
#define PCIE_PORT_SERVICE_AER_SHIFT 1 /* Advanced Error Reporting */
|
|
||||||
#define PCIE_PORT_SERVICE_AER (1 << PCIE_PORT_SERVICE_AER_SHIFT)
|
|
||||||
#define PCIE_PORT_SERVICE_HP_SHIFT 2 /* Native Hotplug */
|
|
||||||
#define PCIE_PORT_SERVICE_HP (1 << PCIE_PORT_SERVICE_HP_SHIFT)
|
|
||||||
#define PCIE_PORT_SERVICE_VC_SHIFT 3 /* Virtual Channel */
|
|
||||||
#define PCIE_PORT_SERVICE_VC (1 << PCIE_PORT_SERVICE_VC_SHIFT)
|
|
||||||
#define PCIE_PORT_SERVICE_DPC_SHIFT 4 /* Downstream Port Containment */
|
|
||||||
#define PCIE_PORT_SERVICE_DPC (1 << PCIE_PORT_SERVICE_DPC_SHIFT)
|
|
||||||
|
|
||||||
struct pcie_device {
|
|
||||||
int irq; /* Service IRQ/MSI/MSI-X Vector */
|
|
||||||
struct pci_dev *port; /* Root/Upstream/Downstream Port */
|
|
||||||
u32 service; /* Port service this device represents */
|
|
||||||
void *priv_data; /* Service Private Data */
|
|
||||||
struct device device; /* Generic Device Interface */
|
|
||||||
};
|
|
||||||
#define to_pcie_device(d) container_of(d, struct pcie_device, device)
|
|
||||||
|
|
||||||
static inline void set_service_data(struct pcie_device *dev, void *data)
|
|
||||||
{
|
|
||||||
dev->priv_data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void *get_service_data(struct pcie_device *dev)
|
|
||||||
{
|
|
||||||
return dev->priv_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct pcie_port_service_driver {
|
|
||||||
const char *name;
|
|
||||||
int (*probe) (struct pcie_device *dev);
|
|
||||||
void (*remove) (struct pcie_device *dev);
|
|
||||||
int (*suspend) (struct pcie_device *dev);
|
|
||||||
int (*resume) (struct pcie_device *dev);
|
|
||||||
|
|
||||||
/* Device driver may resume normal operations */
|
|
||||||
void (*error_resume)(struct pci_dev *dev);
|
|
||||||
|
|
||||||
/* Link Reset Capability - AER service driver specific */
|
|
||||||
pci_ers_result_t (*reset_link) (struct pci_dev *dev);
|
|
||||||
|
|
||||||
int port_type; /* Type of the port this driver can handle */
|
|
||||||
u32 service; /* Port service this device represents */
|
|
||||||
|
|
||||||
struct device_driver driver;
|
|
||||||
};
|
|
||||||
#define to_service_driver(d) \
|
|
||||||
container_of(d, struct pcie_port_service_driver, driver)
|
|
||||||
|
|
||||||
int pcie_port_service_register(struct pcie_port_service_driver *new);
|
|
||||||
void pcie_port_service_unregister(struct pcie_port_service_driver *new);
|
|
||||||
|
|
||||||
#endif /* _PCIEPORT_IF_H_ */
|
|
Reference in New Issue
Block a user