diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/pciehp_ctrl.c | 6 | ||||
-rw-r--r-- | drivers/pci/msi.c | 10 | ||||
-rw-r--r-- | drivers/pci/pci.c | 12 | ||||
-rw-r--r-- | drivers/pci/pcie/aspm.c | 19 |
4 files changed, 29 insertions, 18 deletions
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 10c9c0ba8ff2..ec0b4c11ccd9 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -31,7 +31,6 @@ #include <linux/kernel.h> #include <linux/types.h> #include <linux/slab.h> -#include <linux/pm_runtime.h> #include <linux/pci.h> #include "../pci.h" #include "pciehp.h" @@ -99,7 +98,6 @@ static int board_added(struct slot *p_slot) pciehp_green_led_blink(p_slot); /* Check link training status */ - pm_runtime_get_sync(&ctrl->pcie->port->dev); retval = pciehp_check_link_status(ctrl); if (retval) { ctrl_err(ctrl, "Failed to check link status\n"); @@ -120,14 +118,12 @@ static int board_added(struct slot *p_slot) if (retval != -EEXIST) goto err_exit; } - pm_runtime_put(&ctrl->pcie->port->dev); pciehp_green_led_on(p_slot); pciehp_set_attention_status(p_slot, 0); return 0; err_exit: - pm_runtime_put(&ctrl->pcie->port->dev); set_slot_off(ctrl, p_slot); return retval; } @@ -141,9 +137,7 @@ static int remove_board(struct slot *p_slot) int retval; struct controller *ctrl = p_slot->ctrl; - pm_runtime_get_sync(&ctrl->pcie->port->dev); retval = pciehp_unconfigure_device(p_slot); - pm_runtime_put(&ctrl->pcie->port->dev); if (retval) return retval; diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 50c5003295ca..7f73bacf13ed 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -1206,6 +1206,16 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs, if (flags & PCI_IRQ_AFFINITY) { if (!affd) affd = &msi_default_affd; + + if (affd->pre_vectors + affd->post_vectors > min_vecs) + return -EINVAL; + + /* + * If there aren't any vectors left after applying the pre/post + * vectors don't bother with assigning affinity. + */ + if (affd->pre_vectors + affd->post_vectors == min_vecs) + affd = NULL; } else { if (WARN_ON(affd)) affd = NULL; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index a881c0d3d2e8..7904d02ffdb9 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2241,10 +2241,13 @@ bool pci_bridge_d3_possible(struct pci_dev *bridge) return false; /* - * Hotplug ports handled by firmware in System Management Mode + * Hotplug interrupts cannot be delivered if the link is down, + * so parents of a hotplug port must stay awake. In addition, + * hotplug ports handled by firmware in System Management Mode * may not be put into D3 by the OS (Thunderbolt on non-Macs). + * For simplicity, disallow in general for now. */ - if (bridge->is_hotplug_bridge && !pciehp_is_native(bridge)) + if (bridge->is_hotplug_bridge) return false; if (pci_bridge_d3_force) @@ -2276,10 +2279,7 @@ static int pci_dev_check_d3cold(struct pci_dev *dev, void *data) !pci_pme_capable(dev, PCI_D3cold)) || /* If it is a bridge it must be allowed to go to D3. */ - !pci_power_manageable(dev) || - - /* Hotplug interrupts cannot be delivered if the link is down. */ - dev->is_hotplug_bridge) + !pci_power_manageable(dev)) *d3cold_ok = false; diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 17ac1dce3286..3dd8bcbb3011 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -532,25 +532,32 @@ static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev) link = kzalloc(sizeof(*link), GFP_KERNEL); if (!link) return NULL; + INIT_LIST_HEAD(&link->sibling); INIT_LIST_HEAD(&link->children); INIT_LIST_HEAD(&link->link); link->pdev = pdev; - if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) { + + /* + * Root Ports and PCI/PCI-X to PCIe Bridges are roots of PCIe + * hierarchies. + */ + if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT || + pci_pcie_type(pdev) == PCI_EXP_TYPE_PCIE_BRIDGE) { + link->root = link; + } else { struct pcie_link_state *parent; + parent = pdev->bus->parent->self->link_state; if (!parent) { kfree(link); return NULL; } + link->parent = parent; + link->root = link->parent->root; list_add(&link->link, &parent->children); } - /* Setup a pointer to the root port link */ - if (!link->parent) - link->root = link; - else - link->root = link->parent->root; list_add(&link->sibling, &link_list); pdev->link_state = link; |