summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2006-12-21 17:01:10 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2007-02-07 15:50:05 -0800
commit262303fe329a51463925f3749aafc358a4201397 (patch)
treef9b82b164c8a25d94c9602d640f1b853e7633295
parent44ef4cefb0168740184ee3d7d18254339741e9d5 (diff)
pciehp: fix wait command completion
This patch fixes this problem that pciehp driver will sleep unnecessarily long when waiting for command completion. With this patch, modprobe pciehp driver becomes very faster as follows for instance. o Without this patch # time /sbin/modprobe pciehp real 0m4.976s user 0m0.000s sys 0m0.004s o With this patch # time /sbin/modprobe pciehp real 0m0.640s user 0m0.000s sys 0m0.004s Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/pci/hotplug/pciehp.h1
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c27
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);
}