diff options
Diffstat (limited to 'drivers/pci/hotplug/pciehp_hpc.c')
| -rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 129 | 
1 files changed, 98 insertions, 31 deletions
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 891f81a0400c..79f104963166 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c  | |||
| @@ -247,14 +247,38 @@ static inline void pciehp_free_irq(struct controller *ctrl) | |||
| 247 | free_irq(ctrl->pci_dev->irq, ctrl); | 247 | free_irq(ctrl->pci_dev->irq, ctrl); | 
| 248 | } | 248 | } | 
| 249 | 249 | ||
| 250 | static inline int pcie_wait_cmd(struct controller *ctrl) | 250 | static inline int pcie_poll_cmd(struct controller *ctrl) | 
| 251 | { | ||
| 252 | u16 slot_status; | ||
| 253 | int timeout = 1000; | ||
| 254 | |||
| 255 | if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status)) | ||
| 256 | if (slot_status & CMD_COMPLETED) | ||
| 257 | goto completed; | ||
| 258 | for (timeout = 1000; timeout > 0; timeout -= 100) { | ||
| 259 | msleep(100); | ||
| 260 | if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status)) | ||
| 261 | if (slot_status & CMD_COMPLETED) | ||
| 262 | goto completed; | ||
| 263 | } | ||
| 264 | return 0; /* timeout */ | ||
| 265 | |||
| 266 | completed: | ||
| 267 | pciehp_writew(ctrl, SLOTSTATUS, CMD_COMPLETED); | ||
| 268 | return timeout; | ||
| 269 | } | ||
| 270 | |||
| 271 | static inline int pcie_wait_cmd(struct controller *ctrl, int poll) | ||
| 251 | { | 272 | { | 
| 252 | int retval = 0; | 273 | int retval = 0; | 
| 253 | unsigned int msecs = pciehp_poll_mode ? 2500 : 1000; | 274 | unsigned int msecs = pciehp_poll_mode ? 2500 : 1000; | 
| 254 | unsigned long timeout = msecs_to_jiffies(msecs); | 275 | unsigned long timeout = msecs_to_jiffies(msecs); | 
| 255 | int rc; | 276 | int rc; | 
| 256 | 277 | ||
| 257 | rc = wait_event_interruptible_timeout(ctrl->queue, | 278 | if (poll) | 
| 279 | rc = pcie_poll_cmd(ctrl); | ||
| 280 | else | ||
| 281 | rc = wait_event_interruptible_timeout(ctrl->queue, | ||
| 258 | !ctrl->cmd_busy, timeout); | 282 | !ctrl->cmd_busy, timeout); | 
| 259 | if (!rc) | 283 | if (!rc) | 
| 260 | dbg("Command not completed in 1000 msec\n"); | 284 | dbg("Command not completed in 1000 msec\n"); | 
| @@ -286,12 +310,28 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) | |||
| 286 | goto out; | 310 | goto out; | 
| 287 | } | 311 | } | 
| 288 | 312 | ||
| 289 | if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { | 313 | if (slot_status & CMD_COMPLETED) { | 
| 290 | /* After 1 sec and CMD_COMPLETED still not set, just | 314 | if (!ctrl->no_cmd_complete) { | 
| 291 | proceed forward to issue the next command according | 315 | /* | 
| 292 | to spec. Just print out the error message */ | 316 | * After 1 sec and CMD_COMPLETED still not set, just | 
| 293 | dbg("%s: CMD_COMPLETED not clear after 1 sec.\n", | 317 | * proceed forward to issue the next command according | 
| 294 | __func__); | 318 | * to spec. Just print out the error message. | 
| 319 | */ | ||
| 320 | dbg("%s: CMD_COMPLETED not clear after 1 sec.\n", | ||
| 321 | __func__); | ||
| 322 | } else if (!NO_CMD_CMPL(ctrl)) { | ||
| 323 | /* | ||
| 324 | * This controller semms to notify of command completed | ||
| 325 | * event even though it supports none of power | ||
| 326 | * controller, attention led, power led and EMI. | ||
| 327 | */ | ||
| 328 | dbg("%s: Unexpected CMD_COMPLETED. Need to wait for " | ||
| 329 | "command completed event.\n", __func__); | ||
| 330 | ctrl->no_cmd_complete = 0; | ||
| 331 | } else { | ||
| 332 | dbg("%s: Unexpected CMD_COMPLETED. Maybe the " | ||
| 333 | "controller is broken.\n", __func__); | ||
| 334 | } | ||
| 295 | } | 335 | } | 
| 296 | 336 | ||
| 297 | retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | 337 | retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | 
| @@ -315,8 +355,18 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) | |||
| 315 | /* | 355 | /* | 
| 316 | * Wait for command completion. | 356 | * Wait for command completion. | 
| 317 | */ | 357 | */ | 
| 318 | if (!retval) | 358 | if (!retval && !ctrl->no_cmd_complete) { | 
| 319 | retval = pcie_wait_cmd(ctrl); | 359 | int poll = 0; | 
| 360 | /* | ||
| 361 | * if hotplug interrupt is not enabled or command | ||
| 362 | * completed interrupt is not enabled, we need to poll | ||
| 363 | * command completed event. | ||
| 364 | */ | ||
| 365 | if (!(slot_ctrl & HP_INTR_ENABLE) || | ||
| 366 | !(slot_ctrl & CMD_CMPL_INTR_ENABLE)) | ||
| 367 | poll = 1; | ||
| 368 | retval = pcie_wait_cmd(ctrl, poll); | ||
| 369 | } | ||
| 320 | out: | 370 | out: | 
| 321 | mutex_unlock(&ctrl->ctrl_lock); | 371 | mutex_unlock(&ctrl->ctrl_lock); | 
| 322 | return retval; | 372 | return retval; | 
| @@ -704,13 +754,6 @@ static int hpc_power_off_slot(struct slot * slot) | |||
| 704 | } | 754 | } | 
| 705 | dbg("%s: SLOTCTRL %x write cmd %x\n", | 755 | dbg("%s: SLOTCTRL %x write cmd %x\n", | 
| 706 | __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); | 756 | __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); | 
| 707 | |||
| 708 | /* | ||
| 709 | * After turning power off, we must wait for at least 1 second | ||
| 710 | * before taking any action that relies on power having been | ||
| 711 | * removed from the slot/adapter. | ||
| 712 | */ | ||
| 713 | msleep(1000); | ||
| 714 | out: | 757 | out: | 
| 715 | if (changed) | 758 | if (changed) | 
| 716 | pcie_unmask_bad_dllp(ctrl); | 759 | pcie_unmask_bad_dllp(ctrl); | 
| @@ -722,6 +765,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
| 722 | { | 765 | { | 
| 723 | struct controller *ctrl = (struct controller *)dev_id; | 766 | struct controller *ctrl = (struct controller *)dev_id; | 
| 724 | u16 detected, intr_loc; | 767 | u16 detected, intr_loc; | 
| 768 | struct slot *p_slot; | ||
| 725 | 769 | ||
| 726 | /* | 770 | /* | 
| 727 | * In order to guarantee that all interrupt events are | 771 | * In order to guarantee that all interrupt events are | 
| @@ -756,21 +800,38 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
| 756 | wake_up_interruptible(&ctrl->queue); | 800 | wake_up_interruptible(&ctrl->queue); | 
| 757 | } | 801 | } | 
| 758 | 802 | ||
| 803 | if (!(intr_loc & ~CMD_COMPLETED)) | ||
| 804 | return IRQ_HANDLED; | ||
| 805 | |||
| 806 | /* | ||
| 807 | * Return without handling events if this handler routine is | ||
| 808 | * called before controller initialization is done. This may | ||
| 809 | * happen if hotplug event or another interrupt that shares | ||
| 810 | * the IRQ with pciehp arrives before slot initialization is | ||
| 811 | * done after interrupt handler is registered. | ||
| 812 | * | ||
| 813 | * FIXME - Need more structural fixes. We need to be ready to | ||
| 814 | * handle the event before installing interrupt handler. | ||
| 815 | */ | ||
| 816 | p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); | ||
| 817 | if (!p_slot || !p_slot->hpc_ops) | ||
| 818 | return IRQ_HANDLED; | ||
| 819 | |||
| 759 | /* Check MRL Sensor Changed */ | 820 | /* Check MRL Sensor Changed */ | 
| 760 | if (intr_loc & MRL_SENS_CHANGED) | 821 | if (intr_loc & MRL_SENS_CHANGED) | 
| 761 | pciehp_handle_switch_change(0, ctrl); | 822 | pciehp_handle_switch_change(p_slot); | 
| 762 | 823 | ||
| 763 | /* Check Attention Button Pressed */ | 824 | /* Check Attention Button Pressed */ | 
| 764 | if (intr_loc & ATTN_BUTTN_PRESSED) | 825 | if (intr_loc & ATTN_BUTTN_PRESSED) | 
| 765 | pciehp_handle_attention_button(0, ctrl); | 826 | pciehp_handle_attention_button(p_slot); | 
| 766 | 827 | ||
| 767 | /* Check Presence Detect Changed */ | 828 | /* Check Presence Detect Changed */ | 
| 768 | if (intr_loc & PRSN_DETECT_CHANGED) | 829 | if (intr_loc & PRSN_DETECT_CHANGED) | 
| 769 | pciehp_handle_presence_change(0, ctrl); | 830 | pciehp_handle_presence_change(p_slot); | 
| 770 | 831 | ||
| 771 | /* Check Power Fault Detected */ | 832 | /* Check Power Fault Detected */ | 
| 772 | if (intr_loc & PWR_FAULT_DETECTED) | 833 | if (intr_loc & PWR_FAULT_DETECTED) | 
| 773 | pciehp_handle_power_fault(0, ctrl); | 834 | pciehp_handle_power_fault(p_slot); | 
| 774 | 835 | ||
| 775 | return IRQ_HANDLED; | 836 | return IRQ_HANDLED; | 
| 776 | } | 837 | } | 
| @@ -1028,6 +1089,12 @@ static int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) | |||
| 1028 | static int pcie_init_hardware_part1(struct controller *ctrl, | 1089 | static int pcie_init_hardware_part1(struct controller *ctrl, | 
| 1029 | struct pcie_device *dev) | 1090 | struct pcie_device *dev) | 
| 1030 | { | 1091 | { | 
| 1092 | /* Clear all remaining event bits in Slot Status register */ | ||
| 1093 | if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) { | ||
| 1094 | err("%s: Cannot write to SLOTSTATUS register\n", __func__); | ||
| 1095 | return -1; | ||
| 1096 | } | ||
| 1097 | |||
| 1031 | /* Mask Hot-plug Interrupt Enable */ | 1098 | /* Mask Hot-plug Interrupt Enable */ | 
| 1032 | if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) { | 1099 | if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) { | 
| 1033 | err("%s: Cannot mask hotplug interrupt enable\n", __func__); | 1100 | err("%s: Cannot mask hotplug interrupt enable\n", __func__); | 
| @@ -1040,16 +1107,6 @@ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev) | |||
| 1040 | { | 1107 | { | 
| 1041 | u16 cmd, mask; | 1108 | u16 cmd, mask; | 
| 1042 | 1109 | ||
| 1043 | /* | ||
| 1044 | * We need to clear all events before enabling hotplug interrupt | ||
| 1045 | * notification mechanism in order for hotplug controler to | ||
| 1046 | * generate interrupts. | ||
| 1047 | */ | ||
| 1048 | if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) { | ||
| 1049 | err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); | ||
| 1050 | return -1; | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | cmd = PRSN_DETECT_ENABLE; | 1110 | cmd = PRSN_DETECT_ENABLE; | 
| 1054 | if (ATTN_BUTTN(ctrl)) | 1111 | if (ATTN_BUTTN(ctrl)) | 
| 1055 | cmd |= ATTN_BUTTN_ENABLE; | 1112 | cmd |= ATTN_BUTTN_ENABLE; | 
| @@ -1116,6 +1173,7 @@ static inline void dbg_ctrl(struct controller *ctrl) | |||
| 1116 | dbg(" Power Indicator : %3s\n", PWR_LED(ctrl) ? "yes" : "no"); | 1173 | dbg(" Power Indicator : %3s\n", PWR_LED(ctrl) ? "yes" : "no"); | 
| 1117 | dbg(" Hot-Plug Surprise : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no"); | 1174 | dbg(" Hot-Plug Surprise : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no"); | 
| 1118 | dbg(" EMI Present : %3s\n", EMI(ctrl) ? "yes" : "no"); | 1175 | dbg(" EMI Present : %3s\n", EMI(ctrl) ? "yes" : "no"); | 
| 1176 | dbg(" Comamnd Completed : %3s\n", NO_CMD_CMPL(ctrl)? "no" : "yes"); | ||
| 1119 | pciehp_readw(ctrl, SLOTSTATUS, ®16); | 1177 | pciehp_readw(ctrl, SLOTSTATUS, ®16); | 
| 1120 | dbg("Slot Status : 0x%04x\n", reg16); | 1178 | dbg("Slot Status : 0x%04x\n", reg16); | 
| 1121 | pciehp_readw(ctrl, SLOTSTATUS, ®16); | 1179 | pciehp_readw(ctrl, SLOTSTATUS, ®16); | 
| @@ -1147,6 +1205,15 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev) | |||
| 1147 | mutex_init(&ctrl->ctrl_lock); | 1205 | mutex_init(&ctrl->ctrl_lock); | 
| 1148 | init_waitqueue_head(&ctrl->queue); | 1206 | init_waitqueue_head(&ctrl->queue); | 
| 1149 | dbg_ctrl(ctrl); | 1207 | dbg_ctrl(ctrl); | 
| 1208 | /* | ||
| 1209 | * Controller doesn't notify of command completion if the "No | ||
| 1210 | * Command Completed Support" bit is set in Slot Capability | ||
| 1211 | * register or the controller supports none of power | ||
| 1212 | * controller, attention led, power led and EMI. | ||
| 1213 | */ | ||
| 1214 | if (NO_CMD_CMPL(ctrl) || | ||
| 1215 | !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl))) | ||
| 1216 | ctrl->no_cmd_complete = 1; | ||
| 1150 | 1217 | ||
| 1151 | info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", | 1218 | info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", | 
| 1152 | pdev->vendor, pdev->device, | 1219 | pdev->vendor, pdev->device, | 
