diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2014-06-13 19:58:35 (GMT) |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2014-06-16 17:47:59 (GMT) |
commit | 4283c70e91dcabe36f3545afabc5ee2b7d4da34a (patch) | |
tree | a21257faabcd4bff13e254e4a3c7a3446f2ca459 /drivers | |
parent | 62e4492c3063048a163d238cd1734273f2fc757d (diff) | |
download | linux-4283c70e91dcabe36f3545afabc5ee2b7d4da34a.tar.xz |
PCI: pciehp: Make pcie_wait_cmd() self-contained
pcie_wait_cmd() waits for the controller to finish a hotplug command. Move
the associated logic (to determine whether waiting is required and whether
we're using interrupts or polling) from pcie_write_cmd() to
pcie_wait_cmd().
No functional change.
Tested-by: Rajat Jain <rajatxjain@gmail.com> (IDT 807a controller)
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pci/hotplug/pciehp.h | 1 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 33 |
2 files changed, 18 insertions, 16 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 8e9012d..f7bc886 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -92,6 +92,7 @@ struct controller { struct slot *slot; wait_queue_head_t queue; /* sleep & wake process */ u32 slot_cap; + u32 slot_ctrl; struct timer_list poll_timer; unsigned int cmd_busy:1; unsigned int no_cmd_complete:1; diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 42914e0..7c2a9dd 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -129,16 +129,27 @@ static int pcie_poll_cmd(struct controller *ctrl) return 0; /* timeout */ } -static void pcie_wait_cmd(struct controller *ctrl, int poll) +static void pcie_wait_cmd(struct controller *ctrl) { unsigned int msecs = pciehp_poll_mode ? 2500 : 1000; unsigned long timeout = msecs_to_jiffies(msecs); int rc; - if (poll) - rc = pcie_poll_cmd(ctrl); - else + /* + * If the controller does not generate notifications for command + * completions, we never need to wait between writes. + */ + if (ctrl->no_cmd_complete) + return; + + if (!ctrl->cmd_busy) + return; + + if (ctrl->slot_ctrl & PCI_EXP_SLTCTL_HPIE && + ctrl->slot_ctrl & PCI_EXP_SLTCTL_CCIE) rc = wait_event_timeout(ctrl->queue, !ctrl->cmd_busy, timeout); + else + rc = pcie_poll_cmd(ctrl); if (!rc) ctrl_dbg(ctrl, "Command not completed in 1000 msec\n"); } @@ -187,22 +198,12 @@ static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) ctrl->cmd_busy = 1; smp_mb(); pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl); + ctrl->slot_ctrl = slot_ctrl; /* * Wait for command completion. */ - if (!ctrl->no_cmd_complete) { - int poll = 0; - /* - * if hotplug interrupt is not enabled or command - * completed interrupt is not enabled, we need to poll - * command completed event. - */ - if (!(slot_ctrl & PCI_EXP_SLTCTL_HPIE) || - !(slot_ctrl & PCI_EXP_SLTCTL_CCIE)) - poll = 1; - pcie_wait_cmd(ctrl, poll); - } + pcie_wait_cmd(ctrl); mutex_unlock(&ctrl->ctrl_lock); } |