From e3d27b62110c1ccea4d015f7c5c92f92150668db Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Mon, 6 Jun 2022 16:33:05 -0400 Subject: s390/sclp: detect the zPCI load/store interpretation facility Detect the zPCI Load/Store Interpretation facility. Reviewed-by: Eric Farman Reviewed-by: Christian Borntraeger Reviewed-by: Claudio Imbrenda Signed-off-by: Matthew Rosato Link: https://lore.kernel.org/r/20220606203325.110625-2-mjrosato@linux.ibm.com Signed-off-by: Christian Borntraeger --- drivers/s390/char/sclp_early.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/s390') diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index dd313ff57df3..d5671c03d5cc 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -45,6 +45,7 @@ static void __init sclp_early_facilities_detect(void) sclp.has_gisaf = !!(sccb->fac118 & 0x08); sclp.has_hvs = !!(sccb->fac119 & 0x80); sclp.has_kss = !!(sccb->fac98 & 0x01); + sclp.has_zpci_lsi = !!(sccb->fac118 & 0x01); if (sccb->fac85 & 0x02) S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP; if (sccb->fac91 & 0x40) -- cgit v1.2.3 From 9db153f4523069a89cab14ab9aa2438976f256fb Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Mon, 6 Jun 2022 16:33:06 -0400 Subject: s390/sclp: detect the AISII facility Detect the Adapter Interruption Source ID Interpretation facility. Reviewed-by: Eric Farman Reviewed-by: Christian Borntraeger Reviewed-by: Claudio Imbrenda Signed-off-by: Matthew Rosato Link: https://lore.kernel.org/r/20220606203325.110625-3-mjrosato@linux.ibm.com Signed-off-by: Christian Borntraeger --- arch/s390/include/asm/sclp.h | 1 + drivers/s390/char/sclp_early.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/s390') diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index 68ef0ddf6400..d05fbffa7692 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h @@ -89,6 +89,7 @@ struct sclp_info { unsigned char has_dirq : 1; unsigned char has_iplcc : 1; unsigned char has_zpci_lsi : 1; + unsigned char has_aisii : 1; unsigned int ibc; unsigned int mtid; unsigned int mtid_cp; diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index d5671c03d5cc..39c9bd7e1c26 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -45,6 +45,7 @@ static void __init sclp_early_facilities_detect(void) sclp.has_gisaf = !!(sccb->fac118 & 0x08); sclp.has_hvs = !!(sccb->fac119 & 0x80); sclp.has_kss = !!(sccb->fac98 & 0x01); + sclp.has_aisii = !!(sccb->fac118 & 0x40); sclp.has_zpci_lsi = !!(sccb->fac118 & 0x01); if (sccb->fac85 & 0x02) S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP; -- cgit v1.2.3 From efef0db77c939f105f7dc92a736dd66628406822 Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Mon, 6 Jun 2022 16:33:07 -0400 Subject: s390/sclp: detect the AENI facility Detect the Adapter Event Notification Interpretation facility. Reviewed-by: Eric Farman Reviewed-by: Christian Borntraeger Reviewed-by: Claudio Imbrenda Signed-off-by: Matthew Rosato Link: https://lore.kernel.org/r/20220606203325.110625-4-mjrosato@linux.ibm.com Signed-off-by: Christian Borntraeger --- arch/s390/include/asm/sclp.h | 1 + drivers/s390/char/sclp_early.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/s390') diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index d05fbffa7692..b0e67414c492 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h @@ -90,6 +90,7 @@ struct sclp_info { unsigned char has_iplcc : 1; unsigned char has_zpci_lsi : 1; unsigned char has_aisii : 1; + unsigned char has_aeni : 1; unsigned int ibc; unsigned int mtid; unsigned int mtid_cp; diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index 39c9bd7e1c26..aefdf0b17dbe 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -46,6 +46,7 @@ static void __init sclp_early_facilities_detect(void) sclp.has_hvs = !!(sccb->fac119 & 0x80); sclp.has_kss = !!(sccb->fac98 & 0x01); sclp.has_aisii = !!(sccb->fac118 & 0x40); + sclp.has_aeni = !!(sccb->fac118 & 0x20); sclp.has_zpci_lsi = !!(sccb->fac118 & 0x01); if (sccb->fac85 & 0x02) S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP; -- cgit v1.2.3 From b05a870c5e4e6a113b7f3fb61b5fa0869e40dd30 Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Mon, 6 Jun 2022 16:33:08 -0400 Subject: s390/sclp: detect the AISI facility Detect the Adapter Interruption Suppression Interpretation facility. Reviewed-by: Eric Farman Reviewed-by: Christian Borntraeger Reviewed-by: Claudio Imbrenda Signed-off-by: Matthew Rosato Link: https://lore.kernel.org/r/20220606203325.110625-5-mjrosato@linux.ibm.com Signed-off-by: Christian Borntraeger --- arch/s390/include/asm/sclp.h | 1 + drivers/s390/char/sclp_early.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/s390') diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index b0e67414c492..addefe8ccdba 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h @@ -91,6 +91,7 @@ struct sclp_info { unsigned char has_zpci_lsi : 1; unsigned char has_aisii : 1; unsigned char has_aeni : 1; + unsigned char has_aisi : 1; unsigned int ibc; unsigned int mtid; unsigned int mtid_cp; diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index aefdf0b17dbe..d15b0d541de3 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -47,6 +47,7 @@ static void __init sclp_early_facilities_detect(void) sclp.has_kss = !!(sccb->fac98 & 0x01); sclp.has_aisii = !!(sccb->fac118 & 0x40); sclp.has_aeni = !!(sccb->fac118 & 0x20); + sclp.has_aisi = !!(sccb->fac118 & 0x10); sclp.has_zpci_lsi = !!(sccb->fac118 & 0x01); if (sccb->fac85 & 0x02) S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP; -- cgit v1.2.3 From d2197485a1883c60d044146b1ee69aac654c55e8 Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Mon, 6 Jun 2022 16:33:09 -0400 Subject: s390/airq: pass more TPI info to airq handlers A subsequent patch will introduce an airq handler that requires additional TPI information beyond directed vs floating, so pass the entire tpi_info structure via the handler. Only pci actually uses this information today, for the other airq handlers this is effectively a no-op. Reviewed-by: Eric Farman Reviewed-by: Claudio Imbrenda Reviewed-by: Pierre Morel Reviewed-by: Thomas Huth Acked-by: Christian Borntraeger Acked-by: Cornelia Huck Signed-off-by: Matthew Rosato Link: https://lore.kernel.org/r/20220606203325.110625-6-mjrosato@linux.ibm.com Signed-off-by: Christian Borntraeger --- arch/s390/include/asm/airq.h | 3 ++- arch/s390/kvm/interrupt.c | 4 +++- arch/s390/pci/pci_irq.c | 9 +++++++-- drivers/s390/cio/airq.c | 2 +- drivers/s390/cio/qdio_thinint.c | 6 ++++-- drivers/s390/crypto/ap_bus.c | 9 ++++++--- drivers/s390/virtio/virtio_ccw.c | 4 +++- 7 files changed, 26 insertions(+), 11 deletions(-) (limited to 'drivers/s390') diff --git a/arch/s390/include/asm/airq.h b/arch/s390/include/asm/airq.h index 01936fdfaddb..7918a7d09028 100644 --- a/arch/s390/include/asm/airq.h +++ b/arch/s390/include/asm/airq.h @@ -12,10 +12,11 @@ #include #include +#include struct airq_struct { struct hlist_node list; /* Handler queueing. */ - void (*handler)(struct airq_struct *airq, bool floating); + void (*handler)(struct airq_struct *airq, struct tpi_info *tpi_info); u8 *lsi_ptr; /* Local-Summary-Indicator pointer */ u8 lsi_mask; /* Local-Summary-Indicator mask */ u8 isc; /* Interrupt-subclass */ diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index af96dc0549a4..17ff475157d8 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "kvm-s390.h" #include "gaccess.h" #include "trace-s390.h" @@ -3311,7 +3312,8 @@ out: } EXPORT_SYMBOL_GPL(kvm_s390_gisc_unregister); -static void gib_alert_irq_handler(struct airq_struct *airq, bool floating) +static void gib_alert_irq_handler(struct airq_struct *airq, + struct tpi_info *tpi_info) { inc_irq_stat(IRQIO_GAL); process_gib_alert_list(); diff --git a/arch/s390/pci/pci_irq.c b/arch/s390/pci/pci_irq.c index 500cd2dbdf53..b805c75252ed 100644 --- a/arch/s390/pci/pci_irq.c +++ b/arch/s390/pci/pci_irq.c @@ -11,6 +11,7 @@ #include #include +#include static enum {FLOATING, DIRECTED} irq_delivery; @@ -216,8 +217,11 @@ static void zpci_handle_fallback_irq(void) } } -static void zpci_directed_irq_handler(struct airq_struct *airq, bool floating) +static void zpci_directed_irq_handler(struct airq_struct *airq, + struct tpi_info *tpi_info) { + bool floating = !tpi_info->directed_irq; + if (floating) { inc_irq_stat(IRQIO_PCF); zpci_handle_fallback_irq(); @@ -227,7 +231,8 @@ static void zpci_directed_irq_handler(struct airq_struct *airq, bool floating) } } -static void zpci_floating_irq_handler(struct airq_struct *airq, bool floating) +static void zpci_floating_irq_handler(struct airq_struct *airq, + struct tpi_info *tpi_info) { unsigned long si, ai; struct airq_iv *aibv; diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index c0ed364bf446..230eb5b5b64e 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c @@ -99,7 +99,7 @@ static irqreturn_t do_airq_interrupt(int irq, void *dummy) rcu_read_lock(); hlist_for_each_entry_rcu(airq, head, list) if ((*airq->lsi_ptr & airq->lsi_mask) != 0) - airq->handler(airq, !tpi_info->directed_irq); + airq->handler(airq, tpi_info); rcu_read_unlock(); return IRQ_HANDLED; diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index 8e09bf3a2fcd..9b9335dd06db 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "cio.h" #include "ioasm.h" @@ -93,9 +94,10 @@ static inline u32 clear_shared_ind(void) /** * tiqdio_thinint_handler - thin interrupt handler for qdio * @airq: pointer to adapter interrupt descriptor - * @floating: flag to recognize floating vs. directed interrupts (unused) + * @tpi_info: interrupt information (e.g. floating vs directed -- unused) */ -static void tiqdio_thinint_handler(struct airq_struct *airq, bool floating) +static void tiqdio_thinint_handler(struct airq_struct *airq, + struct tpi_info *tpi_info) { u64 irq_time = S390_lowcore.int_clock; u32 si_used = clear_shared_ind(); diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 5c13d2079d96..1b85f21c151b 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -131,7 +132,8 @@ static int ap_max_adapter_id = 63; static struct bus_type ap_bus_type; /* Adapter interrupt definitions */ -static void ap_interrupt_handler(struct airq_struct *airq, bool floating); +static void ap_interrupt_handler(struct airq_struct *airq, + struct tpi_info *tpi_info); static bool ap_irq_flag; @@ -452,9 +454,10 @@ static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused) /** * ap_interrupt_handler() - Schedule ap_tasklet on interrupt * @airq: pointer to adapter interrupt descriptor - * @floating: ignored + * @tpi_info: ignored */ -static void ap_interrupt_handler(struct airq_struct *airq, bool floating) +static void ap_interrupt_handler(struct airq_struct *airq, + struct tpi_info *tpi_info) { inc_irq_stat(IRQIO_APB); tasklet_schedule(&ap_tasklet); diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c index 97e51c34e6cf..58cca50996ee 100644 --- a/drivers/s390/virtio/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c @@ -33,6 +33,7 @@ #include #include #include +#include /* * virtio related functions @@ -204,7 +205,8 @@ static void drop_airq_indicator(struct virtqueue *vq, struct airq_info *info) write_unlock_irqrestore(&info->lock, flags); } -static void virtio_airq_handler(struct airq_struct *airq, bool floating) +static void virtio_airq_handler(struct airq_struct *airq, + struct tpi_info *tpi_info) { struct airq_info *info = container_of(airq, struct airq_info, airq); unsigned long ai; -- cgit v1.2.3 From 932b646727f9df312980d175e339248cdf7812f0 Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Mon, 6 Jun 2022 16:33:10 -0400 Subject: s390/airq: allow for airq structure that uses an input vector When doing device passthrough where interrupts are being forwarded from host to guest, we wish to use a pinned section of guest memory as the vector (the same memory used by the guest as the vector). To accomplish this, add a new parameter for airq_iv_create which allows passing an existing vector to be used instead of allocating a new one. The caller is responsible for ensuring the vector is pinned in memory as well as for unpinning the memory when the vector is no longer needed. A subsequent patch will use this new parameter for zPCI interpretation. Reviewed-by: Thomas Huth Reviewed-by: Pierre Morel Reviewed-by: Claudio Imbrenda Acked-by: Cornelia Huck Signed-off-by: Matthew Rosato Link: https://lore.kernel.org/r/20220606203325.110625-7-mjrosato@linux.ibm.com Signed-off-by: Christian Borntraeger --- arch/s390/include/asm/airq.h | 4 +++- arch/s390/pci/pci_irq.c | 8 ++++---- drivers/s390/cio/airq.c | 10 +++++++--- drivers/s390/virtio/virtio_ccw.c | 2 +- 4 files changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers/s390') diff --git a/arch/s390/include/asm/airq.h b/arch/s390/include/asm/airq.h index 7918a7d09028..e82e5626e139 100644 --- a/arch/s390/include/asm/airq.h +++ b/arch/s390/include/asm/airq.h @@ -47,8 +47,10 @@ struct airq_iv { #define AIRQ_IV_PTR 4 /* Allocate the ptr array */ #define AIRQ_IV_DATA 8 /* Allocate the data array */ #define AIRQ_IV_CACHELINE 16 /* Cacheline alignment for the vector */ +#define AIRQ_IV_GUESTVEC 32 /* Vector is a pinned guest page */ -struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags); +struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags, + unsigned long *vec); void airq_iv_release(struct airq_iv *iv); unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num); void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num); diff --git a/arch/s390/pci/pci_irq.c b/arch/s390/pci/pci_irq.c index b805c75252ed..87c7d121c255 100644 --- a/arch/s390/pci/pci_irq.c +++ b/arch/s390/pci/pci_irq.c @@ -296,7 +296,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) zdev->aisb = bit; /* Create adapter interrupt vector */ - zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK); + zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK, NULL); if (!zdev->aibv) return -ENOMEM; @@ -419,7 +419,7 @@ static int __init zpci_directed_irq_init(void) union zpci_sic_iib iib = {{0}}; unsigned int cpu; - zpci_sbv = airq_iv_create(num_possible_cpus(), 0); + zpci_sbv = airq_iv_create(num_possible_cpus(), 0, NULL); if (!zpci_sbv) return -ENOMEM; @@ -441,7 +441,7 @@ static int __init zpci_directed_irq_init(void) zpci_ibv[cpu] = airq_iv_create(cache_line_size() * BITS_PER_BYTE, AIRQ_IV_DATA | AIRQ_IV_CACHELINE | - (!cpu ? AIRQ_IV_ALLOC : 0)); + (!cpu ? AIRQ_IV_ALLOC : 0), NULL); if (!zpci_ibv[cpu]) return -ENOMEM; } @@ -458,7 +458,7 @@ static int __init zpci_floating_irq_init(void) if (!zpci_ibv) return -ENOMEM; - zpci_sbv = airq_iv_create(ZPCI_NR_DEVICES, AIRQ_IV_ALLOC); + zpci_sbv = airq_iv_create(ZPCI_NR_DEVICES, AIRQ_IV_ALLOC, NULL); if (!zpci_sbv) goto out_free; diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index 230eb5b5b64e..34967e67249e 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c @@ -122,10 +122,12 @@ static inline unsigned long iv_size(unsigned long bits) * airq_iv_create - create an interrupt vector * @bits: number of bits in the interrupt vector * @flags: allocation flags + * @vec: pointer to pinned guest memory if AIRQ_IV_GUESTVEC * * Returns a pointer to an interrupt vector structure */ -struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags) +struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags, + unsigned long *vec) { struct airq_iv *iv; unsigned long size; @@ -146,6 +148,8 @@ struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags) &iv->vector_dma); if (!iv->vector) goto out_free; + } else if (flags & AIRQ_IV_GUESTVEC) { + iv->vector = vec; } else { iv->vector = cio_dma_zalloc(size); if (!iv->vector) @@ -185,7 +189,7 @@ out_free: kfree(iv->avail); if (iv->flags & AIRQ_IV_CACHELINE && iv->vector) dma_pool_free(airq_iv_cache, iv->vector, iv->vector_dma); - else + else if (!(iv->flags & AIRQ_IV_GUESTVEC)) cio_dma_free(iv->vector, size); kfree(iv); out: @@ -204,7 +208,7 @@ void airq_iv_release(struct airq_iv *iv) kfree(iv->bitlock); if (iv->flags & AIRQ_IV_CACHELINE) dma_pool_free(airq_iv_cache, iv->vector, iv->vector_dma); - else + else if (!(iv->flags & AIRQ_IV_GUESTVEC)) cio_dma_free(iv->vector, iv_size(iv->bits)); kfree(iv->avail); kfree(iv); diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c index 58cca50996ee..51bef226d33f 100644 --- a/drivers/s390/virtio/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c @@ -242,7 +242,7 @@ static struct airq_info *new_airq_info(int index) return NULL; rwlock_init(&info->lock); info->aiv = airq_iv_create(VIRTIO_IV_BITS, AIRQ_IV_ALLOC | AIRQ_IV_PTR - | AIRQ_IV_CACHELINE); + | AIRQ_IV_CACHELINE, NULL); if (!info->aiv) { kfree(info); return NULL; -- cgit v1.2.3