Commit 932b6467 authored by Matthew Rosato's avatar Matthew Rosato Committed by Christian Borntraeger

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: default avatarThomas Huth <thuth@redhat.com>
Reviewed-by: default avatarPierre Morel <pmorel@linux.ibm.com>
Reviewed-by: default avatarClaudio Imbrenda <imbrenda@linux.ibm.com>
Acked-by: default avatarCornelia Huck <cohuck@redhat.com>
Signed-off-by: default avatarMatthew Rosato <mjrosato@linux.ibm.com>
Link: https://lore.kernel.org/r/20220606203325.110625-7-mjrosato@linux.ibm.comSigned-off-by: default avatarChristian Borntraeger <borntraeger@linux.ibm.com>
parent d2197485
...@@ -47,8 +47,10 @@ struct airq_iv { ...@@ -47,8 +47,10 @@ struct airq_iv {
#define AIRQ_IV_PTR 4 /* Allocate the ptr array */ #define AIRQ_IV_PTR 4 /* Allocate the ptr array */
#define AIRQ_IV_DATA 8 /* Allocate the data array */ #define AIRQ_IV_DATA 8 /* Allocate the data array */
#define AIRQ_IV_CACHELINE 16 /* Cacheline alignment for the vector */ #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); void airq_iv_release(struct airq_iv *iv);
unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num); 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); void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num);
......
...@@ -296,7 +296,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) ...@@ -296,7 +296,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
zdev->aisb = bit; zdev->aisb = bit;
/* Create adapter interrupt vector */ /* 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) if (!zdev->aibv)
return -ENOMEM; return -ENOMEM;
...@@ -419,7 +419,7 @@ static int __init zpci_directed_irq_init(void) ...@@ -419,7 +419,7 @@ static int __init zpci_directed_irq_init(void)
union zpci_sic_iib iib = {{0}}; union zpci_sic_iib iib = {{0}};
unsigned int cpu; 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) if (!zpci_sbv)
return -ENOMEM; return -ENOMEM;
...@@ -441,7 +441,7 @@ static int __init zpci_directed_irq_init(void) ...@@ -441,7 +441,7 @@ static int __init zpci_directed_irq_init(void)
zpci_ibv[cpu] = airq_iv_create(cache_line_size() * BITS_PER_BYTE, zpci_ibv[cpu] = airq_iv_create(cache_line_size() * BITS_PER_BYTE,
AIRQ_IV_DATA | AIRQ_IV_DATA |
AIRQ_IV_CACHELINE | AIRQ_IV_CACHELINE |
(!cpu ? AIRQ_IV_ALLOC : 0)); (!cpu ? AIRQ_IV_ALLOC : 0), NULL);
if (!zpci_ibv[cpu]) if (!zpci_ibv[cpu])
return -ENOMEM; return -ENOMEM;
} }
...@@ -458,7 +458,7 @@ static int __init zpci_floating_irq_init(void) ...@@ -458,7 +458,7 @@ static int __init zpci_floating_irq_init(void)
if (!zpci_ibv) if (!zpci_ibv)
return -ENOMEM; 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) if (!zpci_sbv)
goto out_free; goto out_free;
......
...@@ -122,10 +122,12 @@ static inline unsigned long iv_size(unsigned long bits) ...@@ -122,10 +122,12 @@ static inline unsigned long iv_size(unsigned long bits)
* airq_iv_create - create an interrupt vector * airq_iv_create - create an interrupt vector
* @bits: number of bits in the interrupt vector * @bits: number of bits in the interrupt vector
* @flags: allocation flags * @flags: allocation flags
* @vec: pointer to pinned guest memory if AIRQ_IV_GUESTVEC
* *
* Returns a pointer to an interrupt vector structure * 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; struct airq_iv *iv;
unsigned long size; unsigned long size;
...@@ -146,6 +148,8 @@ struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags) ...@@ -146,6 +148,8 @@ struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags)
&iv->vector_dma); &iv->vector_dma);
if (!iv->vector) if (!iv->vector)
goto out_free; goto out_free;
} else if (flags & AIRQ_IV_GUESTVEC) {
iv->vector = vec;
} else { } else {
iv->vector = cio_dma_zalloc(size); iv->vector = cio_dma_zalloc(size);
if (!iv->vector) if (!iv->vector)
...@@ -185,7 +189,7 @@ struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags) ...@@ -185,7 +189,7 @@ struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags)
kfree(iv->avail); kfree(iv->avail);
if (iv->flags & AIRQ_IV_CACHELINE && iv->vector) if (iv->flags & AIRQ_IV_CACHELINE && iv->vector)
dma_pool_free(airq_iv_cache, iv->vector, iv->vector_dma); 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); cio_dma_free(iv->vector, size);
kfree(iv); kfree(iv);
out: out:
...@@ -204,7 +208,7 @@ void airq_iv_release(struct airq_iv *iv) ...@@ -204,7 +208,7 @@ void airq_iv_release(struct airq_iv *iv)
kfree(iv->bitlock); kfree(iv->bitlock);
if (iv->flags & AIRQ_IV_CACHELINE) if (iv->flags & AIRQ_IV_CACHELINE)
dma_pool_free(airq_iv_cache, iv->vector, iv->vector_dma); 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)); cio_dma_free(iv->vector, iv_size(iv->bits));
kfree(iv->avail); kfree(iv->avail);
kfree(iv); kfree(iv);
......
...@@ -242,7 +242,7 @@ static struct airq_info *new_airq_info(int index) ...@@ -242,7 +242,7 @@ static struct airq_info *new_airq_info(int index)
return NULL; return NULL;
rwlock_init(&info->lock); rwlock_init(&info->lock);
info->aiv = airq_iv_create(VIRTIO_IV_BITS, AIRQ_IV_ALLOC | AIRQ_IV_PTR info->aiv = airq_iv_create(VIRTIO_IV_BITS, AIRQ_IV_ALLOC | AIRQ_IV_PTR
| AIRQ_IV_CACHELINE); | AIRQ_IV_CACHELINE, NULL);
if (!info->aiv) { if (!info->aiv) {
kfree(info); kfree(info);
return NULL; return NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment