s390/pci: do not require AIS facility
authorChristian Borntraeger <borntraeger@de.ibm.com>
Mon, 30 Oct 2017 13:38:58 +0000 (14:38 +0100)
committerHeiko Carstens <heiko.carstens@de.ibm.com>
Wed, 8 Nov 2017 08:47:39 +0000 (09:47 +0100)
As of today QEMU does not provide the AIS facility to its guest.  This
prevents Linux guests from using PCI devices as the ais facility is
checked during init. As this is just a performance optimization, we can
move the ais check into the code where we need it (calling the SIC
instruction). This is used at initialization and on interrupt. Both
places do not require any serialization, so we can simply skip the
instruction.

Since we will now get all interrupts, we can also avoid the 2nd scan.
As we can have multiple interrupts in parallel we might trigger spurious
irqs more often for the non-AIS case but the core code can handle that.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Pierre Morel <pmorel@linux.vnet.ibm.com>
Reviewed-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Acked-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
arch/s390/include/asm/pci_insn.h
arch/s390/pci/pci.c
arch/s390/pci/pci_insn.c

index 34abcf2757995cdcc69a397d60f61cd1e5804ad3..a74efc02ad2c9a3d57074f3e907f024fd09eb5ef 100644 (file)
@@ -81,6 +81,6 @@ int zpci_refresh_trans(u64 fn, u64 addr, u64 range);
 int zpci_load(u64 *data, u64 req, u64 offset);
 int zpci_store(u64 data, u64 req, u64 offset);
 int zpci_store_block(const u64 *data, u64 req, u64 offset);
-void zpci_set_irq_ctrl(u16 ctl, char *unused, u8 isc);
+int zpci_set_irq_ctrl(u16 ctl, char *unused, u8 isc);
 
 #endif
index a25d95a6612dd90f9ff009764a1d318e087495b0..0fe649c0d5423a2ed51fcff4dc7d011204fdf4e9 100644 (file)
@@ -368,7 +368,8 @@ static void zpci_irq_handler(struct airq_struct *airq)
                                /* End of second scan with interrupts on. */
                                break;
                        /* First scan complete, reenable interrupts. */
-                       zpci_set_irq_ctrl(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC);
+                       if (zpci_set_irq_ctrl(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC))
+                               break;
                        si = 0;
                        continue;
                }
@@ -956,7 +957,7 @@ static int __init pci_base_init(void)
        if (!s390_pci_probe)
                return 0;
 
-       if (!test_facility(69) || !test_facility(71) || !test_facility(72))
+       if (!test_facility(69) || !test_facility(71))
                return 0;
 
        rc = zpci_debug_init();
index ea34086c86744e0e19cd072f160592efa2d1c7fa..81b840bc6e4e733064d20f309bb57f24820f01cb 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/export.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
+#include <asm/facility.h>
 #include <asm/pci_insn.h>
 #include <asm/pci_debug.h>
 #include <asm/processor.h>
@@ -91,11 +92,14 @@ int zpci_refresh_trans(u64 fn, u64 addr, u64 range)
 }
 
 /* Set Interruption Controls */
-void zpci_set_irq_ctrl(u16 ctl, char *unused, u8 isc)
+int zpci_set_irq_ctrl(u16 ctl, char *unused, u8 isc)
 {
+       if (!test_facility(72))
+               return -EIO;
        asm volatile (
                "       .insn   rsy,0xeb00000000d1,%[ctl],%[isc],%[u]\n"
                : : [ctl] "d" (ctl), [isc] "d" (isc << 27), [u] "Q" (*unused));
+       return 0;
 }
 
 /* PCI Load */