mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 04:31:50 +00:00
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 <thuth@redhat.com> Reviewed-by: Pierre Morel <pmorel@linux.ibm.com> Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com> Acked-by: Cornelia Huck <cohuck@redhat.com> Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com> Link: https://lore.kernel.org/r/20220606203325.110625-7-mjrosato@linux.ibm.com Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
This commit is contained in:
parent
d2197485a1
commit
932b646727
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user