aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/pnv_php.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug/pnv_php.c')
-rw-r--r--drivers/pci/hotplug/pnv_php.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/pci/hotplug/pnv_php.c b/drivers/pci/hotplug/pnv_php.c
index 41304b313512..63cd9f354b79 100644
--- a/drivers/pci/hotplug/pnv_php.c
+++ b/drivers/pci/hotplug/pnv_php.c
@@ -717,7 +717,8 @@ static irqreturn_t pnv_php_interrupt(int irq, void *data)
717 if (sts & PCI_EXP_SLTSTA_DLLSC) { 717 if (sts & PCI_EXP_SLTSTA_DLLSC) {
718 pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lsts); 718 pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lsts);
719 added = !!(lsts & PCI_EXP_LNKSTA_DLLLA); 719 added = !!(lsts & PCI_EXP_LNKSTA_DLLLA);
720 } else if (sts & PCI_EXP_SLTSTA_PDC) { 720 } else if (!(php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC) &&
721 (sts & PCI_EXP_SLTSTA_PDC)) {
721 ret = pnv_pci_get_presence_state(php_slot->id, &presence); 722 ret = pnv_pci_get_presence_state(php_slot->id, &presence);
722 if (ret) { 723 if (ret) {
723 dev_warn(&pdev->dev, "PCI slot [%s] error %d getting presence (0x%04x), to retry the operation.\n", 724 dev_warn(&pdev->dev, "PCI slot [%s] error %d getting presence (0x%04x), to retry the operation.\n",
@@ -768,6 +769,7 @@ static irqreturn_t pnv_php_interrupt(int irq, void *data)
768static void pnv_php_init_irq(struct pnv_php_slot *php_slot, int irq) 769static void pnv_php_init_irq(struct pnv_php_slot *php_slot, int irq)
769{ 770{
770 struct pci_dev *pdev = php_slot->pdev; 771 struct pci_dev *pdev = php_slot->pdev;
772 u32 broken_pdc = 0;
771 u16 sts, ctrl; 773 u16 sts, ctrl;
772 int ret; 774 int ret;
773 775
@@ -779,9 +781,18 @@ static void pnv_php_init_irq(struct pnv_php_slot *php_slot, int irq)
779 return; 781 return;
780 } 782 }
781 783
784 /* Check PDC (Presence Detection Change) is broken or not */
785 ret = of_property_read_u32(php_slot->dn, "ibm,slot-broken-pdc",
786 &broken_pdc);
787 if (!ret && broken_pdc)
788 php_slot->flags |= PNV_PHP_FLAG_BROKEN_PDC;
789
782 /* Clear pending interrupts */ 790 /* Clear pending interrupts */
783 pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &sts); 791 pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &sts);
784 sts |= (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC); 792 if (php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC)
793 sts |= PCI_EXP_SLTSTA_DLLSC;
794 else
795 sts |= (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC);
785 pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, sts); 796 pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, sts);
786 797
787 /* Request the interrupt */ 798 /* Request the interrupt */
@@ -795,9 +806,15 @@ static void pnv_php_init_irq(struct pnv_php_slot *php_slot, int irq)
795 806
796 /* Enable the interrupts */ 807 /* Enable the interrupts */
797 pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &ctrl); 808 pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &ctrl);
798 ctrl |= (PCI_EXP_SLTCTL_HPIE | 809 if (php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC) {
799 PCI_EXP_SLTCTL_PDCE | 810 ctrl &= ~PCI_EXP_SLTCTL_PDCE;
800 PCI_EXP_SLTCTL_DLLSCE); 811 ctrl |= (PCI_EXP_SLTCTL_HPIE |
812 PCI_EXP_SLTCTL_DLLSCE);
813 } else {
814 ctrl |= (PCI_EXP_SLTCTL_HPIE |
815 PCI_EXP_SLTCTL_PDCE |
816 PCI_EXP_SLTCTL_DLLSCE);
817 }
801 pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, ctrl); 818 pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, ctrl);
802 819
803 /* The interrupt is initialized successfully when @irq is valid */ 820 /* The interrupt is initialized successfully when @irq is valid */