aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2008-05-27 06:04:30 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2008-05-27 18:43:16 -0400
commit5808639bfa98d69f77a481d759570d85f164fea0 (patch)
treef691cf1890db51cb201a64c9420281684bf80608
parentdbd79aed1aea2bece0bf43cc2ff3b2f9baf48a08 (diff)
pciehp: fix slow probing
Fix the "pciehp probing slow" problem reported from Jan C. Nordholz in http://bugzilla.kernel.org/show_bug.cgi?id=10751. The command completed bit in Slot Status register applies only to commands issued to control the attention indicator, power indicator, power controller, or electromechanical interlock. However, writes to other parts of the Slot Control register would end up writing to the control fields. Hence, any write to Slot Control register is considered as a command. However, if the controller doesn't support any of attention indicator, power indicator, power controller and electromechanical interlock, command completed bit would not set in writing to Slot Control register. In this case, we should not wait for command completed bit set, otherwise all commands would be considered not completed in timeout seconds (1 sec.). The cause of the problem is pciehp driver didn't take this situation into account. This patch changes pciehp to take it into account. This patch also add the check for "No Command Completed Support" bit in Slot Capability register. If it is set, we should not wait for command completed bit set as well. This problem seems to be revealed by the commit c27fb883dffe11aa4cb35ecea1fa1832ba45d4da that fixed the bug that pciehp did not wait for command completed properly (pciehp just ignored the command completion event). Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r--drivers/pci/hotplug/pciehp.h3
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c40
2 files changed, 36 insertions, 7 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 920091c4b18d..79c9ddaad3fb 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -97,6 +97,7 @@ struct controller {
97 u8 cap_base; 97 u8 cap_base;
98 struct timer_list poll_timer; 98 struct timer_list poll_timer;
99 volatile int cmd_busy; 99 volatile int cmd_busy;
100 unsigned int no_cmd_complete:1;
100}; 101};
101 102
102#define INT_BUTTON_IGNORE 0 103#define INT_BUTTON_IGNORE 0
@@ -135,6 +136,7 @@ struct controller {
135#define PWR_LED_PRSN 0x00000010 136#define PWR_LED_PRSN 0x00000010
136#define HP_SUPR_RM_SUP 0x00000020 137#define HP_SUPR_RM_SUP 0x00000020
137#define EMI_PRSN 0x00020000 138#define EMI_PRSN 0x00020000
139#define NO_CMD_CMPL_SUP 0x00040000
138 140
139#define ATTN_BUTTN(ctrl) ((ctrl)->slot_cap & ATTN_BUTTN_PRSN) 141#define ATTN_BUTTN(ctrl) ((ctrl)->slot_cap & ATTN_BUTTN_PRSN)
140#define POWER_CTRL(ctrl) ((ctrl)->slot_cap & PWR_CTRL_PRSN) 142#define POWER_CTRL(ctrl) ((ctrl)->slot_cap & PWR_CTRL_PRSN)
@@ -143,6 +145,7 @@ struct controller {
143#define PWR_LED(ctrl) ((ctrl)->slot_cap & PWR_LED_PRSN) 145#define PWR_LED(ctrl) ((ctrl)->slot_cap & PWR_LED_PRSN)
144#define HP_SUPR_RM(ctrl) ((ctrl)->slot_cap & HP_SUPR_RM_SUP) 146#define HP_SUPR_RM(ctrl) ((ctrl)->slot_cap & HP_SUPR_RM_SUP)
145#define EMI(ctrl) ((ctrl)->slot_cap & EMI_PRSN) 147#define EMI(ctrl) ((ctrl)->slot_cap & EMI_PRSN)
148#define NO_CMD_CMPL(ctrl) ((ctrl)->slot_cap & NO_CMD_CMPL_SUP)
146 149
147extern int pciehp_sysfs_enable_slot(struct slot *slot); 150extern int pciehp_sysfs_enable_slot(struct slot *slot);
148extern int pciehp_sysfs_disable_slot(struct slot *slot); 151extern int pciehp_sysfs_disable_slot(struct slot *slot);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 425a0f609977..70940fb3fffa 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -286,12 +286,28 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
286 goto out; 286 goto out;
287 } 287 }
288 288
289 if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { 289 if (slot_status & CMD_COMPLETED) {
290 /* After 1 sec and CMD_COMPLETED still not set, just 290 if (!ctrl->no_cmd_complete) {
291 proceed forward to issue the next command according 291 /*
292 to spec. Just print out the error message */ 292 * After 1 sec and CMD_COMPLETED still not set, just
293 dbg("%s: CMD_COMPLETED not clear after 1 sec.\n", 293 * proceed forward to issue the next command according
294 __func__); 294 * to spec. Just print out the error message.
295 */
296 dbg("%s: CMD_COMPLETED not clear after 1 sec.\n",
297 __func__);
298 } else if (!NO_CMD_CMPL(ctrl)) {
299 /*
300 * This controller semms to notify of command completed
301 * event even though it supports none of power
302 * controller, attention led, power led and EMI.
303 */
304 dbg("%s: Unexpected CMD_COMPLETED. Need to wait for "
305 "command completed event.\n", __func__);
306 ctrl->no_cmd_complete = 0;
307 } else {
308 dbg("%s: Unexpected CMD_COMPLETED. Maybe the "
309 "controller is broken.\n", __func__);
310 }
295 } 311 }
296 312
297 retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); 313 retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
@@ -315,7 +331,7 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
315 /* 331 /*
316 * Wait for command completion. 332 * Wait for command completion.
317 */ 333 */
318 if (!retval) 334 if (!retval && !ctrl->no_cmd_complete)
319 retval = pcie_wait_cmd(ctrl); 335 retval = pcie_wait_cmd(ctrl);
320 out: 336 out:
321 mutex_unlock(&ctrl->ctrl_lock); 337 mutex_unlock(&ctrl->ctrl_lock);
@@ -1130,6 +1146,7 @@ static inline void dbg_ctrl(struct controller *ctrl)
1130 dbg(" Power Indicator : %3s\n", PWR_LED(ctrl) ? "yes" : "no"); 1146 dbg(" Power Indicator : %3s\n", PWR_LED(ctrl) ? "yes" : "no");
1131 dbg(" Hot-Plug Surprise : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no"); 1147 dbg(" Hot-Plug Surprise : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no");
1132 dbg(" EMI Present : %3s\n", EMI(ctrl) ? "yes" : "no"); 1148 dbg(" EMI Present : %3s\n", EMI(ctrl) ? "yes" : "no");
1149 dbg(" Comamnd Completed : %3s\n", NO_CMD_CMPL(ctrl)? "no" : "yes");
1133 pciehp_readw(ctrl, SLOTSTATUS, &reg16); 1150 pciehp_readw(ctrl, SLOTSTATUS, &reg16);
1134 dbg("Slot Status : 0x%04x\n", reg16); 1151 dbg("Slot Status : 0x%04x\n", reg16);
1135 pciehp_readw(ctrl, SLOTSTATUS, &reg16); 1152 pciehp_readw(ctrl, SLOTSTATUS, &reg16);
@@ -1161,6 +1178,15 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev)
1161 mutex_init(&ctrl->ctrl_lock); 1178 mutex_init(&ctrl->ctrl_lock);
1162 init_waitqueue_head(&ctrl->queue); 1179 init_waitqueue_head(&ctrl->queue);
1163 dbg_ctrl(ctrl); 1180 dbg_ctrl(ctrl);
1181 /*
1182 * Controller doesn't notify of command completion if the "No
1183 * Command Completed Support" bit is set in Slot Capability
1184 * register or the controller supports none of power
1185 * controller, attention led, power led and EMI.
1186 */
1187 if (NO_CMD_CMPL(ctrl) ||
1188 !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl)))
1189 ctrl->no_cmd_complete = 1;
1164 1190
1165 info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", 1191 info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
1166 pdev->vendor, pdev->device, 1192 pdev->vendor, pdev->device,