diff options
Diffstat (limited to 'drivers/pci/hotplug/pciehp_hpc.c')
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 31 |
1 files changed, 11 insertions, 20 deletions
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index c1a312f24060..07bd32151146 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -548,23 +548,21 @@ static int hpc_power_on_slot(struct slot * slot) | |||
548 | 548 | ||
549 | slot_cmd = POWER_ON; | 549 | slot_cmd = POWER_ON; |
550 | cmd_mask = PCI_EXP_SLTCTL_PCC; | 550 | cmd_mask = PCI_EXP_SLTCTL_PCC; |
551 | /* Enable detection that we turned off at slot power-off time */ | ||
552 | if (!pciehp_poll_mode) { | 551 | if (!pciehp_poll_mode) { |
553 | slot_cmd |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | | 552 | /* Enable power fault detection turned off at power off time */ |
554 | PCI_EXP_SLTCTL_PDCE); | 553 | slot_cmd |= PCI_EXP_SLTCTL_PFDE; |
555 | cmd_mask |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | | 554 | cmd_mask |= PCI_EXP_SLTCTL_PFDE; |
556 | PCI_EXP_SLTCTL_PDCE); | ||
557 | } | 555 | } |
558 | 556 | ||
559 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 557 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); |
560 | |||
561 | if (retval) { | 558 | if (retval) { |
562 | ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd); | 559 | ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd); |
563 | return -1; | 560 | return retval; |
564 | } | 561 | } |
565 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", | 562 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", |
566 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); | 563 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); |
567 | 564 | ||
565 | ctrl->power_fault_detected = 0; | ||
568 | return retval; | 566 | return retval; |
569 | } | 567 | } |
570 | 568 | ||
@@ -621,18 +619,10 @@ static int hpc_power_off_slot(struct slot * slot) | |||
621 | 619 | ||
622 | slot_cmd = POWER_OFF; | 620 | slot_cmd = POWER_OFF; |
623 | cmd_mask = PCI_EXP_SLTCTL_PCC; | 621 | cmd_mask = PCI_EXP_SLTCTL_PCC; |
624 | /* | ||
625 | * If we get MRL or presence detect interrupts now, the isr | ||
626 | * will notice the sticky power-fault bit too and issue power | ||
627 | * indicator change commands. This will lead to an endless loop | ||
628 | * of command completions, since the power-fault bit remains on | ||
629 | * till the slot is powered on again. | ||
630 | */ | ||
631 | if (!pciehp_poll_mode) { | 622 | if (!pciehp_poll_mode) { |
632 | slot_cmd &= ~(PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | | 623 | /* Disable power fault detection */ |
633 | PCI_EXP_SLTCTL_PDCE); | 624 | slot_cmd &= ~PCI_EXP_SLTCTL_PFDE; |
634 | cmd_mask |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | | 625 | cmd_mask |= PCI_EXP_SLTCTL_PFDE; |
635 | PCI_EXP_SLTCTL_PDCE); | ||
636 | } | 626 | } |
637 | 627 | ||
638 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 628 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); |
@@ -710,9 +700,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
710 | pciehp_handle_presence_change(p_slot); | 700 | pciehp_handle_presence_change(p_slot); |
711 | 701 | ||
712 | /* Check Power Fault Detected */ | 702 | /* Check Power Fault Detected */ |
713 | if (intr_loc & PCI_EXP_SLTSTA_PFD) | 703 | if ((intr_loc & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) { |
704 | ctrl->power_fault_detected = 1; | ||
714 | pciehp_handle_power_fault(p_slot); | 705 | pciehp_handle_power_fault(p_slot); |
715 | 706 | } | |
716 | return IRQ_HANDLED; | 707 | return IRQ_HANDLED; |
717 | } | 708 | } |
718 | 709 | ||