diff options
-rw-r--r-- | drivers/pci/hotplug/pciehp.h | 1 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 27 |
2 files changed, 16 insertions, 12 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 17167d59447..927dba9911e 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -100,6 +100,7 @@ struct controller { u16 vendor_id; u8 cap_base; struct timer_list poll_timer; + volatile int cmd_busy; }; #define INT_BUTTON_IGNORE 0 diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 9fbd9b9f982..eb1862b50bb 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -251,20 +251,21 @@ static void start_int_poll_timer(struct controller *ctrl, int sec) static inline int pcie_wait_cmd(struct controller *ctrl) { - DECLARE_WAITQUEUE(wait, current); - - add_wait_queue(&ctrl->queue, &wait); - if (!pciehp_poll_mode) - /* Sleep for up to 1 second */ - msleep_interruptible(1000); - else - msleep_interruptible(2500); + int retval = 0; + unsigned int msecs = pciehp_poll_mode ? 2500 : 1000; + unsigned long timeout = msecs_to_jiffies(msecs); + int rc; - remove_wait_queue(&ctrl->queue, &wait); - if (signal_pending(current)) - return -EINTR; + rc = wait_event_interruptible_timeout(ctrl->queue, + !ctrl->cmd_busy, timeout); + if (!rc) + dbg("Command not completed in 1000 msec\n"); + else if (rc < 0) { + retval = -EINTR; + info("Command was interrupted by a signal\n"); + } - return 0; + return retval; } static int pcie_write_cmd(struct slot *slot, u16 cmd) @@ -291,6 +292,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd) __FUNCTION__); } + ctrl->cmd_busy = 1; retval = pciehp_writew(ctrl, SLOTCTRL, (cmd | CMD_CMPL_INTR_ENABLE)); if (retval) { err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); @@ -773,6 +775,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) /* * Command Complete Interrupt Pending */ + ctrl->cmd_busy = 0; wake_up_interruptible(&ctrl->queue); } |