Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci: PCI hotplug: shpchp: don't blindly claim non-AMD 0x7450 device IDs PCI: pciehp: wait 100 ms after Link Training check PCI: pciehp: wait 1000 ms before Link Training check PCI: pciehp: Retrieve link speed after link is trained PCI: Let PCI_PRI depend on PCI PCI: Fix compile errors with PCI_ATS and !PCI_IOV PCI / ACPI: Make acpiphp ignore root bridges using PCIe native hotplug
This commit is contained in:
commit
09521577ca
8 changed files with 51 additions and 25 deletions
|
@ -76,6 +76,7 @@ config PCI_IOV
|
||||||
|
|
||||||
config PCI_PRI
|
config PCI_PRI
|
||||||
bool "PCI PRI support"
|
bool "PCI PRI support"
|
||||||
|
depends on PCI
|
||||||
select PCI_ATS
|
select PCI_ATS
|
||||||
help
|
help
|
||||||
PRI is the PCI Page Request Interface. It allows PCI devices that are
|
PRI is the PCI Page Request Interface. It allows PCI devices that are
|
||||||
|
|
|
@ -459,8 +459,17 @@ static int add_bridge(acpi_handle handle)
|
||||||
{
|
{
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
unsigned long long tmp;
|
unsigned long long tmp;
|
||||||
|
struct acpi_pci_root *root;
|
||||||
acpi_handle dummy_handle;
|
acpi_handle dummy_handle;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We shouldn't use this bridge if PCIe native hotplug control has been
|
||||||
|
* granted by the BIOS for it.
|
||||||
|
*/
|
||||||
|
root = acpi_pci_find_root(handle);
|
||||||
|
if (root && (root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
/* if the bridge doesn't have _STA, we assume it is always there */
|
/* if the bridge doesn't have _STA, we assume it is always there */
|
||||||
status = acpi_get_handle(handle, "_STA", &dummy_handle);
|
status = acpi_get_handle(handle, "_STA", &dummy_handle);
|
||||||
if (ACPI_SUCCESS(status)) {
|
if (ACPI_SUCCESS(status)) {
|
||||||
|
@ -1376,13 +1385,23 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type,
|
||||||
static acpi_status
|
static acpi_status
|
||||||
find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
|
find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||||
{
|
{
|
||||||
|
struct acpi_pci_root *root;
|
||||||
int *count = (int *)context;
|
int *count = (int *)context;
|
||||||
|
|
||||||
if (acpi_is_root_bridge(handle)) {
|
if (!acpi_is_root_bridge(handle))
|
||||||
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
|
return AE_OK;
|
||||||
handle_hotplug_event_bridge, NULL);
|
|
||||||
(*count)++;
|
root = acpi_pci_find_root(handle);
|
||||||
}
|
if (!root)
|
||||||
|
return AE_OK;
|
||||||
|
|
||||||
|
if (root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL)
|
||||||
|
return AE_OK;
|
||||||
|
|
||||||
|
(*count)++;
|
||||||
|
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
|
||||||
|
handle_hotplug_event_bridge, NULL);
|
||||||
|
|
||||||
return AE_OK ;
|
return AE_OK ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -213,9 +213,6 @@ static int board_added(struct slot *p_slot)
|
||||||
goto err_exit;
|
goto err_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for 1 second after checking link training status */
|
|
||||||
msleep(1000);
|
|
||||||
|
|
||||||
/* Check for a power fault */
|
/* Check for a power fault */
|
||||||
if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) {
|
if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) {
|
||||||
ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
|
ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
|
||||||
|
|
|
@ -280,6 +280,14 @@ int pciehp_check_link_status(struct controller *ctrl)
|
||||||
else
|
else
|
||||||
msleep(1000);
|
msleep(1000);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need to wait for 1000 ms after Data Link Layer Link Active
|
||||||
|
* (DLLLA) bit reads 1b before sending configuration request.
|
||||||
|
* We need it before checking Link Training (LT) bit becuase
|
||||||
|
* LT is still set even after DLLLA bit is set on some platform.
|
||||||
|
*/
|
||||||
|
msleep(1000);
|
||||||
|
|
||||||
retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
|
retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
ctrl_err(ctrl, "Cannot read LNKSTATUS register\n");
|
ctrl_err(ctrl, "Cannot read LNKSTATUS register\n");
|
||||||
|
@ -294,6 +302,16 @@ int pciehp_check_link_status(struct controller *ctrl)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the port supports Link speeds greater than 5.0 GT/s, we
|
||||||
|
* must wait for 100 ms after Link training completes before
|
||||||
|
* sending configuration request.
|
||||||
|
*/
|
||||||
|
if (ctrl->pcie->port->subordinate->max_bus_speed > PCIE_SPEED_5_0GT)
|
||||||
|
msleep(100);
|
||||||
|
|
||||||
|
pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,7 +502,6 @@ int pciehp_power_on_slot(struct slot * slot)
|
||||||
u16 slot_cmd;
|
u16 slot_cmd;
|
||||||
u16 cmd_mask;
|
u16 cmd_mask;
|
||||||
u16 slot_status;
|
u16 slot_status;
|
||||||
u16 lnk_status;
|
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
/* Clear sticky power-fault bit from previous power failures */
|
/* Clear sticky power-fault bit from previous power failures */
|
||||||
|
@ -516,14 +533,6 @@ int pciehp_power_on_slot(struct slot * slot)
|
||||||
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
|
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
|
||||||
pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
|
pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
|
||||||
|
|
||||||
retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
|
|
||||||
if (retval) {
|
|
||||||
ctrl_err(ctrl, "%s: Cannot read LNKSTA register\n",
|
|
||||||
__func__);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -278,8 +278,8 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||||
|
|
||||||
static int is_shpc_capable(struct pci_dev *dev)
|
static int is_shpc_capable(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device ==
|
if (dev->vendor == PCI_VENDOR_ID_AMD &&
|
||||||
PCI_DEVICE_ID_AMD_GOLAM_7450))
|
dev->device == PCI_DEVICE_ID_AMD_GOLAM_7450)
|
||||||
return 1;
|
return 1;
|
||||||
if (!pci_find_capability(dev, PCI_CAP_ID_SHPC))
|
if (!pci_find_capability(dev, PCI_CAP_ID_SHPC))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -944,8 +944,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
|
||||||
ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
|
ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
|
||||||
ctrl_dbg(ctrl, "Hotplug Controller:\n");
|
ctrl_dbg(ctrl, "Hotplug Controller:\n");
|
||||||
|
|
||||||
if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
|
if (pdev->vendor == PCI_VENDOR_ID_AMD &&
|
||||||
PCI_DEVICE_ID_AMD_GOLAM_7450)) {
|
pdev->device == PCI_DEVICE_ID_AMD_GOLAM_7450) {
|
||||||
/* amd shpc driver doesn't use Base Offset; assume 0 */
|
/* amd shpc driver doesn't use Base Offset; assume 0 */
|
||||||
ctrl->mmio_base = pci_resource_start(pdev, 0);
|
ctrl->mmio_base = pci_resource_start(pdev, 0);
|
||||||
ctrl->mmio_size = pci_resource_len(pdev, 0);
|
ctrl->mmio_size = pci_resource_len(pdev, 0);
|
||||||
|
|
|
@ -12,7 +12,7 @@ struct pci_ats {
|
||||||
unsigned int is_enabled:1; /* Enable bit is set */
|
unsigned int is_enabled:1; /* Enable bit is set */
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_PCI_IOV
|
#ifdef CONFIG_PCI_ATS
|
||||||
|
|
||||||
extern int pci_enable_ats(struct pci_dev *dev, int ps);
|
extern int pci_enable_ats(struct pci_dev *dev, int ps);
|
||||||
extern void pci_disable_ats(struct pci_dev *dev);
|
extern void pci_disable_ats(struct pci_dev *dev);
|
||||||
|
@ -29,7 +29,7 @@ static inline int pci_ats_enabled(struct pci_dev *dev)
|
||||||
return dev->ats && dev->ats->is_enabled;
|
return dev->ats && dev->ats->is_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* CONFIG_PCI_IOV */
|
#else /* CONFIG_PCI_ATS */
|
||||||
|
|
||||||
static inline int pci_enable_ats(struct pci_dev *dev, int ps)
|
static inline int pci_enable_ats(struct pci_dev *dev, int ps)
|
||||||
{
|
{
|
||||||
|
@ -50,7 +50,7 @@ static inline int pci_ats_enabled(struct pci_dev *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_PCI_IOV */
|
#endif /* CONFIG_PCI_ATS */
|
||||||
|
|
||||||
#ifdef CONFIG_PCI_PRI
|
#ifdef CONFIG_PCI_PRI
|
||||||
|
|
||||||
|
|
|
@ -338,7 +338,7 @@ struct pci_dev {
|
||||||
struct list_head msi_list;
|
struct list_head msi_list;
|
||||||
#endif
|
#endif
|
||||||
struct pci_vpd *vpd;
|
struct pci_vpd *vpd;
|
||||||
#ifdef CONFIG_PCI_IOV
|
#ifdef CONFIG_PCI_ATS
|
||||||
union {
|
union {
|
||||||
struct pci_sriov *sriov; /* SR-IOV capability related */
|
struct pci_sriov *sriov; /* SR-IOV capability related */
|
||||||
struct pci_dev *physfn; /* the PF this VF is associated with */
|
struct pci_dev *physfn; /* the PF this VF is associated with */
|
||||||
|
|
Loading…
Add table
Reference in a new issue