| From foo@baz Wed Dec 6 18:04:41 CET 2017 |
| From: Christian Borntraeger <borntraeger@de.ibm.com> |
| Date: Mon, 30 Oct 2017 14:38:58 +0100 |
| Subject: s390/pci: do not require AIS facility |
| |
| From: Christian Borntraeger <borntraeger@de.ibm.com> |
| |
| |
| [ Upstream commit 48070c73058be6de9c0d754d441ed7092dfc8f12 ] |
| |
| 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> |
| Signed-off-by: Sasha Levin <alexander.levin@verizon.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/s390/include/asm/pci_insn.h | 2 +- |
| arch/s390/pci/pci.c | 5 +++-- |
| arch/s390/pci/pci_insn.c | 6 +++++- |
| 3 files changed, 9 insertions(+), 4 deletions(-) |
| |
| --- a/arch/s390/include/asm/pci_insn.h |
| +++ b/arch/s390/include/asm/pci_insn.h |
| @@ -82,6 +82,6 @@ int zpci_refresh_trans(u64 fn, u64 addr, |
| 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 |
| --- a/arch/s390/pci/pci.c |
| +++ b/arch/s390/pci/pci.c |
| @@ -368,7 +368,8 @@ static void zpci_irq_handler(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(); |
| --- a/arch/s390/pci/pci_insn.c |
| +++ b/arch/s390/pci/pci_insn.c |
| @@ -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, |
| } |
| |
| /* 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 */ |