diff options
-rw-r--r-- | drivers/pci/hotplug/pciehp.h | 3 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 40 |
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 | ||
147 | extern int pciehp_sysfs_enable_slot(struct slot *slot); | 150 | extern int pciehp_sysfs_enable_slot(struct slot *slot); |
148 | extern int pciehp_sysfs_disable_slot(struct slot *slot); | 151 | extern 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, ®16); | 1150 | pciehp_readw(ctrl, SLOTSTATUS, ®16); |
1134 | dbg("Slot Status : 0x%04x\n", reg16); | 1151 | dbg("Slot Status : 0x%04x\n", reg16); |
1135 | pciehp_readw(ctrl, SLOTSTATUS, ®16); | 1152 | pciehp_readw(ctrl, SLOTSTATUS, ®16); |
@@ -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, |