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, |
