Commit b45873c3 authored by Farhan Ali's avatar Farhan Ali Committed by Heiko Carstens
Browse files

s390/pci: Restore IRQ unconditionally for the zPCI device



Commit c1e18c17 ("s390/pci: add zpci_set_irq()/zpci_clear_irq()"),
introduced the zpci_set_irq() and zpci_clear_irq(), to be used while
resetting a zPCI device.

Commit da995d53 ("s390/pci: implement reset_slot for hotplug
slot"), mentions zpci_clear_irq() being called in the path for
zpci_hot_reset_device().  But that is not the case anymore and these
functions are not called outside of this file. Instead
zpci_hot_reset_device() relies on zpci_disable_device() also clearing
the IRQs, but misses to reset the zdev->irqs_registered flag.

However after a CLP disable/enable reset, the device's IRQ are
unregistered, but the flag zdev->irq_registered does not get cleared. It
creates an inconsistent state and so arch_restore_msi_irqs() doesn't
correctly restore the device's IRQ. This becomes a problem when a PCI
driver tries to restore the state of the device through
pci_restore_state(). Restore IRQ unconditionally for the device and remove
the irq_registered flag as its redundant.

Fixes: c1e18c17 ("s390/pci: add zpci_set_irq()/zpci_clear_irq()")
Cc: stable@vger.kernnel.org
Reviewed-by: default avatarNiklas Schnelle <schnelle@linux.ibm.com>
Reviewed-by: default avatarMatthew Rosato <mjrosato@linux.ibm.com>
Signed-off-by: default avatarFarhan Ali <alifm@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent 840bc67c
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -145,7 +145,6 @@ struct zpci_dev {
	u8		has_resources	: 1;
	u8		is_physfn	: 1;
	u8		util_str_avail	: 1;
	u8		irqs_registered	: 1;
	u8		tid_avail	: 1;
	u8		rtr_avail	: 1; /* Relaxed translation allowed */
	unsigned int	devfn;		/* DEVFN part of the RID*/
+1 −8
Original line number Diff line number Diff line
@@ -107,9 +107,6 @@ static int zpci_set_irq(struct zpci_dev *zdev)
	else
		rc = zpci_set_airq(zdev);

	if (!rc)
		zdev->irqs_registered = 1;

	return rc;
}

@@ -123,9 +120,6 @@ static int zpci_clear_irq(struct zpci_dev *zdev)
	else
		rc = zpci_clear_airq(zdev);

	if (!rc)
		zdev->irqs_registered = 0;

	return rc;
}

@@ -427,7 +421,6 @@ bool arch_restore_msi_irqs(struct pci_dev *pdev)
{
	struct zpci_dev *zdev = to_zpci(pdev);

	if (!zdev->irqs_registered)
	zpci_set_irq(zdev);
	return true;
}