mirror of
https://github.com/torvalds/linux.git
synced 2026-09-13 15:40:03 +02:00
IOMMU fixes for Linux v7.3-rc3:
- RISC-V IOMMU:
- Serialize command queue publication to prevent concurrent producers
from exposing incomplete or out-of-order commands to hardware.
- Wait for queue space outside the command queue lock.
- Avoid waiting for IOFENCE completion when command enqueue failed.
- AMD IOMMU:
- Prevent GA log buffers from being reallocated and leaked during
resume, where allocation also occurs in an unsuitable syscore
callback context.
- Fix a regression on older systems whose firmware advertises
incorrect IOMMU features.
- Preserve allocation errors when assigning host domain IDs to nested
domains.
- s390 IOMMU:
- Prevent a NULL dereference when translating an unmapped IOVA with
five-level ZPCI translation tables.
- Miscellaneous:
- Remove a stale MAINTAINERS entry and clean up unused or redundant
AMD IOMMU declarations, macros, and checks.
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEr9jSbILcajRFYWYyK/BELZcBGuMFAmqkH6kACgkQK/BELZcB
GuPgZhAAtYhzeVbH6IKimy29zj6TZKvzdlWtMOuAk7wj/URPWPK6kA+LC44uH9OB
+WY+6P922vC5pqcL5YkA7GNt8KQaJEgTFp9zdQ15hY7PFAw+GIM66HVVn96iCv5a
RY1485YJopQEHSfpb3e2GyuR6mdW6b7ReEmzFr0P9Md1Flm/6TaGvCmSCjLLVrto
BkJ6DfWQ0zNC3eByAHFE8HOh3T6Eea8J64tC+Tt6jOFO6ynQL7+acwv2zG66z1RM
bZAjgNMAdPO7AHU3Kue7OT8mVFKy75G3AOtT55dobiBWFJ4jPgziw6ZhjEEMNZDs
eADcQT1reXLdQkiOYGxZt5fNAI9RQiZRNizIidFG4KmaYGxWaPUR2nQUxyCSvlig
Wv8GMHaFskZxkJyqAonYtlUxaUk6XAF3L4nQrDZW2KJsHZdopcDnUeGi526J414h
bvD/p4IxSNhlzib+70mQ3XPHqzVAyDjjRBuQBK+B4MXfKMet68/O1qBzxBQVqgQX
gJaz++7hGSE4uvt4NCANjhpC6aTKGZdeWsFc8xs44krHjQo6ssPZSlxl3nclJOUQ
O6N50eV6nItnE/kqbdKxpdZIzYHmW6DLxL+2bvueZjRMXxpCuPmSuCpJux+Hl2RW
RqMVhUAgGPm35RNmRTkAh534WzElNc2K66VM6952ck8xrZ6+Hy8=
=2Cze
-----END PGP SIGNATURE-----
Merge tag 'iommu-fixes-v7.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux
Pull IOMMU fixes from Joerg Roedel:
"RISC-V:
- Serialize command queue publication to prevent concurrent producers
from exposing incomplete or out-of-order commands to hardware
- Wait for queue space outside the command queue lock
- Avoid waiting for IOFENCE completion when command enqueue failed
AMD:
- Prevent GA log buffers from being reallocated and leaked during
resume, where allocation also occurs in an unsuitable syscore
callback context
- Fix a regression on older systems whose firmware advertises
incorrect IOMMU features
- Preserve allocation errors when assigning host domain IDs to nested
domains
s390:
- Prevent a NULL dereference when translating an unmapped IOVA with
five-level ZPCI translation tables
Misc:
- Remove a stale MAINTAINERS entry and clean up unused or redundant
AMD IOMMU declarations, macros, and checks"
* tag 'iommu-fixes-v7.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux:
iommu/amd: Remove unused macro
iommu/amd: Remove redundant checks from interrupt handler path
iommu/amd: Remove redundant check in irq_remapping_select()
iommu/amd: Make iommu_sva_set_dev_pasid as static
MAINTAINERS: Drop the nonexistent vsi-iommu.h file entry
iommu/amd: Fix ineffective error check in nested domain allocation
iommu/amd: Fix premature break in init_iommu_one() again
iommu/amd: Do not reallocate GA log buffers on resume
iommu/s390: Fix NULL dereference in iova_to_phys() with ZPCI_TABLE_TYPE_RFX
iommu/riscv: Avoid waiting on failed command enqueue
iommu/riscv: Serialize command queue publishing
iommu/riscv: Add command queue lock
This commit is contained in:
commit
f6e213d5a2
|
|
@ -28609,7 +28609,6 @@ L: iommu@lists.linux.dev
|
|||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iommu/verisilicon,iommu.yaml
|
||||
F: drivers/iommu/vsi-iommu.c
|
||||
F: include/linux/vsi-iommu.h
|
||||
|
||||
VF610 NAND DRIVER
|
||||
M: Stefan Agner <stefan@agner.ch>
|
||||
|
|
|
|||
|
|
@ -54,9 +54,6 @@ struct protection_domain *protection_domain_alloc(void);
|
|||
struct iommu_domain *amd_iommu_domain_alloc_sva(struct device *dev,
|
||||
struct mm_struct *mm);
|
||||
void amd_iommu_domain_free(struct iommu_domain *dom);
|
||||
int iommu_sva_set_dev_pasid(struct iommu_domain *domain,
|
||||
struct device *dev, ioasid_t pasid,
|
||||
struct iommu_domain *old);
|
||||
void amd_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid,
|
||||
struct iommu_domain *domain);
|
||||
|
||||
|
|
|
|||
|
|
@ -39,18 +39,6 @@
|
|||
#define MMIO_RANGE_OFFSET 0x0c
|
||||
#define MMIO_MISC_OFFSET 0x10
|
||||
|
||||
/* Masks, shifts and macros to parse the device range capability */
|
||||
#define MMIO_RANGE_LD_MASK 0xff000000
|
||||
#define MMIO_RANGE_FD_MASK 0x00ff0000
|
||||
#define MMIO_RANGE_BUS_MASK 0x0000ff00
|
||||
#define MMIO_RANGE_LD_SHIFT 24
|
||||
#define MMIO_RANGE_FD_SHIFT 16
|
||||
#define MMIO_RANGE_BUS_SHIFT 8
|
||||
#define MMIO_GET_LD(x) (((x) & MMIO_RANGE_LD_MASK) >> MMIO_RANGE_LD_SHIFT)
|
||||
#define MMIO_GET_FD(x) (((x) & MMIO_RANGE_FD_MASK) >> MMIO_RANGE_FD_SHIFT)
|
||||
#define MMIO_GET_BUS(x) (((x) & MMIO_RANGE_BUS_MASK) >> MMIO_RANGE_BUS_SHIFT)
|
||||
#define MMIO_MSI_NUM(x) ((x) & 0x1f)
|
||||
|
||||
/* Used offsets into the MMIO space */
|
||||
#define MMIO_DEV_TABLE_OFFSET 0x0000
|
||||
#define MMIO_CMD_BUF_OFFSET 0x0008
|
||||
|
|
@ -247,7 +235,6 @@
|
|||
|
||||
/* constants to configure the command buffer */
|
||||
#define CMD_BUFFER_SIZE 8192
|
||||
#define CMD_BUFFER_UNINITIALIZED 1
|
||||
#define CMD_BUFFER_ENTRIES 512
|
||||
#define MMIO_CMD_SIZE_SHIFT 56
|
||||
#define MMIO_CMD_SIZE_512 (0x9ULL << MMIO_CMD_SIZE_SHIFT)
|
||||
|
|
@ -434,9 +421,6 @@ struct irq_remap_table {
|
|||
u32 *table;
|
||||
};
|
||||
|
||||
/* Interrupt remapping feature used? */
|
||||
extern bool amd_iommu_irq_remap;
|
||||
|
||||
extern const struct iommu_ops amd_iommu_ops;
|
||||
|
||||
/* IVRS indicates that pre-boot remapping was enabled */
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ struct ivmd_header {
|
|||
} __attribute__((packed));
|
||||
|
||||
bool amd_iommu_dump;
|
||||
bool amd_iommu_irq_remap __read_mostly;
|
||||
static bool amd_iommu_irq_remap __read_mostly;
|
||||
|
||||
enum protection_domain_mode amd_iommu_pgtable = PD_MODE_V1;
|
||||
/* Virtual address size */
|
||||
|
|
@ -909,7 +909,9 @@ static void free_ga_log(struct amd_iommu *iommu)
|
|||
{
|
||||
#ifdef CONFIG_IRQ_REMAP
|
||||
iommu_free_pages(iommu->ga_log);
|
||||
iommu->ga_log = NULL;
|
||||
iommu_free_pages(iommu->ga_log_tail);
|
||||
iommu->ga_log_tail = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -956,6 +958,9 @@ static int iommu_init_ga_log(struct amd_iommu *iommu)
|
|||
if (WARN_ON_ONCE(!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir)))
|
||||
return -EINVAL;
|
||||
|
||||
if (iommu->ga_log && iommu->ga_log_tail)
|
||||
return 0;
|
||||
|
||||
iommu->ga_log = iommu_alloc_pages_node_sz(nid, GFP_KERNEL, GA_LOG_SIZE);
|
||||
if (!iommu->ga_log)
|
||||
goto err_out;
|
||||
|
|
@ -1917,19 +1922,20 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h,
|
|||
else
|
||||
iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
|
||||
|
||||
/* XT and GAM require GA mode. */
|
||||
if ((h->efr_reg & (0x1 << IOMMU_EFR_GASUP_SHIFT)) == 0) {
|
||||
amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
|
||||
} else {
|
||||
if (h->efr_reg & BIT(IOMMU_EFR_XTSUP_SHIFT))
|
||||
amd_iommu_xt_mode = IRQ_REMAP_X2APIC_MODE;
|
||||
}
|
||||
|
||||
if (h->efr_attr & BIT(IOMMU_IVHD_ATTR_HATDIS_SHIFT)) {
|
||||
pr_warn_once("Host Address Translation is not supported.\n");
|
||||
amd_iommu_hatdis = true;
|
||||
}
|
||||
|
||||
/* XT and GAM require GA mode. */
|
||||
if ((h->efr_reg & (0x1 << IOMMU_EFR_GASUP_SHIFT)) == 0) {
|
||||
amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
|
||||
break;
|
||||
} else {
|
||||
if (h->efr_reg & BIT(IOMMU_EFR_XTSUP_SHIFT))
|
||||
amd_iommu_xt_mode = IRQ_REMAP_X2APIC_MODE;
|
||||
}
|
||||
|
||||
early_iommu_features_init(iommu, h);
|
||||
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1076,9 +1076,6 @@ static void iommu_poll_ga_log(struct amd_iommu *iommu)
|
|||
{
|
||||
u32 head, tail;
|
||||
|
||||
if (iommu->ga_log == NULL)
|
||||
return;
|
||||
|
||||
head = readl(iommu->mmio_base + MMIO_GA_HEAD_OFFSET);
|
||||
tail = readl(iommu->mmio_base + MMIO_GA_TAIL_OFFSET);
|
||||
|
||||
|
|
@ -3976,9 +3973,6 @@ static int irq_remapping_select(struct irq_domain *d, struct irq_fwspec *fwspec,
|
|||
struct amd_iommu *iommu;
|
||||
int devid = -1;
|
||||
|
||||
if (!amd_iommu_irq_remap)
|
||||
return 0;
|
||||
|
||||
if (x86_fwspec_is_ioapic(fwspec))
|
||||
devid = get_ioapic_devid(fwspec->param[0]);
|
||||
else if (x86_fwspec_is_hpet(fwspec))
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ struct iommu_domain *
|
|||
amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags,
|
||||
const struct iommu_user_data *user_data)
|
||||
{
|
||||
int ret;
|
||||
int ret, hdom_id;
|
||||
unsigned long irqflags;
|
||||
struct nested_domain *ndom;
|
||||
struct guest_domain_mapping_info *gdom_info;
|
||||
|
|
@ -161,8 +161,8 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags,
|
|||
}
|
||||
|
||||
/* The gDomID does not exist. We allocate new hdom_id */
|
||||
gdom_info->hdom_id = amd_iommu_pdom_id_alloc();
|
||||
if (gdom_info->hdom_id <= 0) {
|
||||
hdom_id = amd_iommu_pdom_id_alloc();
|
||||
if (hdom_id <= 0) {
|
||||
__xa_cmpxchg(&aviommu->gdomid_array,
|
||||
ndom->gdom_id, gdom_info, NULL, GFP_ATOMIC);
|
||||
xa_unlock_irqrestore(&aviommu->gdomid_array, irqflags);
|
||||
|
|
@ -170,6 +170,7 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags,
|
|||
goto out_err_gdom_info;
|
||||
}
|
||||
|
||||
gdom_info->hdom_id = hdom_id;
|
||||
ndom->gdom_info = gdom_info;
|
||||
refcount_set(&gdom_info->users, 1);
|
||||
|
||||
|
|
|
|||
|
|
@ -99,9 +99,9 @@ static const struct mmu_notifier_ops sva_mn = {
|
|||
.release = sva_mn_release,
|
||||
};
|
||||
|
||||
int iommu_sva_set_dev_pasid(struct iommu_domain *domain,
|
||||
struct device *dev, ioasid_t pasid,
|
||||
struct iommu_domain *old)
|
||||
static int iommu_sva_set_dev_pasid(struct iommu_domain *domain,
|
||||
struct device *dev, ioasid_t pasid,
|
||||
struct iommu_domain *old)
|
||||
{
|
||||
struct pdom_dev_data *pdom_dev_data;
|
||||
struct protection_domain *sva_pdom = to_pdomain(domain);
|
||||
|
|
|
|||
|
|
@ -165,9 +165,6 @@ void amd_iommu_poll_ppr_log(struct amd_iommu *iommu)
|
|||
{
|
||||
u32 head, tail;
|
||||
|
||||
if (iommu->ppr_log == NULL)
|
||||
return;
|
||||
|
||||
head = readl(iommu->mmio_base + MMIO_PPR_HEAD_OFFSET);
|
||||
tail = readl(iommu->mmio_base + MMIO_PPR_TAIL_OFFSET);
|
||||
|
||||
|
|
|
|||
|
|
@ -382,78 +382,97 @@ static int riscv_iommu_queue_wait(struct riscv_iommu_queue *queue,
|
|||
(int)(cons - index) > 0, 0, timeout_us);
|
||||
}
|
||||
|
||||
/* Enqueue an entry and wait to be processed if timeout_us > 0
|
||||
*
|
||||
* Error handling for IOMMU hardware not responding in reasonable time
|
||||
* will be added as separate patch series along with other RAS features.
|
||||
* For now, only report hardware failure and continue.
|
||||
*/
|
||||
static unsigned int riscv_iommu_queue_send(struct riscv_iommu_queue *queue,
|
||||
void *entry, size_t entry_size)
|
||||
static int riscv_iommu_queue_wait_for_space(struct riscv_iommu_queue *queue,
|
||||
unsigned int last)
|
||||
{
|
||||
unsigned int head;
|
||||
unsigned int tail;
|
||||
unsigned int hw_head;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
ret = riscv_iommu_readl_timeout(queue->iommu, Q_HEAD(queue), hw_head,
|
||||
!(hw_head & ~queue->mask) && hw_head != last,
|
||||
0, RISCV_IOMMU_QUEUE_TIMEOUT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
raw_spin_lock_irqsave(&queue->lock, flags);
|
||||
head = atomic_read(&queue->head);
|
||||
tail = atomic_read(&queue->tail);
|
||||
if ((tail - head) >= queue->mask) {
|
||||
last = Q_ITEM(queue, head);
|
||||
/*
|
||||
* Re-read hw_head under the lock so that it is consistent with
|
||||
* the freshly computed 'last'. Using the pre-lock snapshot
|
||||
* could produce a stale value that wraps around relative to the
|
||||
* new 'last', advancing the shadow head past entries that have
|
||||
* not yet been consumed by the hardware.
|
||||
*/
|
||||
hw_head = riscv_iommu_readl(queue->iommu, Q_HEAD(queue));
|
||||
if (!(hw_head & ~queue->mask) && hw_head != last)
|
||||
atomic_add((hw_head - last) & queue->mask, &queue->head);
|
||||
}
|
||||
raw_spin_unlock_irqrestore(&queue->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enqueue an entry and publish it to the hardware queue. */
|
||||
static int riscv_iommu_queue_send(struct riscv_iommu_queue *queue,
|
||||
void *entry, size_t entry_size,
|
||||
unsigned int *out_prod)
|
||||
{
|
||||
unsigned int prod;
|
||||
unsigned int head;
|
||||
unsigned int tail;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
/* Do not preempt submission flow. */
|
||||
local_irq_save(flags);
|
||||
/* 1. Wait for space availability and reserve the next slot. */
|
||||
for (;;) {
|
||||
raw_spin_lock_irqsave(&queue->lock, flags);
|
||||
|
||||
/* 1. Allocate some space in the queue */
|
||||
prod = atomic_inc_return(&queue->prod) - 1;
|
||||
head = atomic_read(&queue->head);
|
||||
prod = atomic_read(&queue->tail);
|
||||
head = atomic_read(&queue->head);
|
||||
|
||||
/* 2. Wait for space availability. */
|
||||
if ((prod - head) > queue->mask) {
|
||||
if (readx_poll_timeout(atomic_read, &queue->head,
|
||||
head, (prod - head) < queue->mask,
|
||||
0, RISCV_IOMMU_QUEUE_TIMEOUT))
|
||||
if ((prod - head) < queue->mask)
|
||||
break;
|
||||
|
||||
head = Q_ITEM(queue, head);
|
||||
raw_spin_unlock_irqrestore(&queue->lock, flags);
|
||||
|
||||
ret = riscv_iommu_queue_wait_for_space(queue, head);
|
||||
if (ret)
|
||||
goto err_busy;
|
||||
} else if ((prod - head) == queue->mask) {
|
||||
const unsigned int last = Q_ITEM(queue, head);
|
||||
|
||||
if (riscv_iommu_readl_timeout(queue->iommu, Q_HEAD(queue), head,
|
||||
!(head & ~queue->mask) && head != last,
|
||||
0, RISCV_IOMMU_QUEUE_TIMEOUT))
|
||||
goto err_busy;
|
||||
atomic_add((head - last) & queue->mask, &queue->head);
|
||||
}
|
||||
|
||||
/* 3. Store entry in the ring buffer */
|
||||
/* 2. Store entry in the ring buffer. */
|
||||
memcpy(queue->base + Q_ITEM(queue, prod) * entry_size, entry, entry_size);
|
||||
|
||||
/* 4. Wait for all previous entries to be ready */
|
||||
if (readx_poll_timeout(atomic_read, &queue->tail, tail, prod == tail,
|
||||
0, RISCV_IOMMU_QUEUE_TIMEOUT))
|
||||
goto err_busy;
|
||||
|
||||
/*
|
||||
* 5. Make sure the ring buffer update (whether in normal or I/O memory) is
|
||||
* completed and visible before signaling the tail doorbell to fetch
|
||||
* the next command. 'fence ow, ow'
|
||||
*/
|
||||
/* 3. Make sure the entry is visible before updating the queue tail. */
|
||||
dma_wmb();
|
||||
riscv_iommu_writel(queue->iommu, Q_TAIL(queue), Q_ITEM(queue, prod + 1));
|
||||
|
||||
/*
|
||||
* 6. Make sure the doorbell write to the device has finished before updating
|
||||
* the shadow tail index in normal memory. 'fence o, w'
|
||||
* 4. Make sure the doorbell write to the device has finished before
|
||||
* updating the shadow tail index in normal memory. 'fence o, w'
|
||||
*/
|
||||
#ifdef CONFIG_MMIOWB
|
||||
mmiowb();
|
||||
#endif
|
||||
atomic_inc(&queue->tail);
|
||||
atomic_set(&queue->tail, prod + 1);
|
||||
atomic_set(&queue->prod, prod + 1);
|
||||
|
||||
/* 7. Complete submission and restore local interrupts */
|
||||
local_irq_restore(flags);
|
||||
if (out_prod)
|
||||
*out_prod = prod;
|
||||
|
||||
return prod;
|
||||
raw_spin_unlock_irqrestore(&queue->lock, flags);
|
||||
return 0;
|
||||
|
||||
err_busy:
|
||||
local_irq_restore(flags);
|
||||
/* Report the failure and continue; full RAS recovery is not implemented. */
|
||||
dev_err_once(queue->iommu->dev, "Hardware error: command enqueue failed\n");
|
||||
|
||||
return prod;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -492,7 +511,7 @@ static irqreturn_t riscv_iommu_cmdq_process(int irq, void *data)
|
|||
static void riscv_iommu_cmd_send(struct riscv_iommu_device *iommu,
|
||||
struct riscv_iommu_command *cmd)
|
||||
{
|
||||
riscv_iommu_queue_send(&iommu->cmdq, cmd, sizeof(*cmd));
|
||||
riscv_iommu_queue_send(&iommu->cmdq, cmd, sizeof(*cmd), NULL);
|
||||
}
|
||||
|
||||
/* Send IOFENCE.C command and wait for all scheduled commands to complete. */
|
||||
|
|
@ -501,9 +520,12 @@ static void riscv_iommu_cmd_sync(struct riscv_iommu_device *iommu,
|
|||
{
|
||||
struct riscv_iommu_command cmd;
|
||||
unsigned int prod;
|
||||
int ret;
|
||||
|
||||
riscv_iommu_cmd_iofence(&cmd);
|
||||
prod = riscv_iommu_queue_send(&iommu->cmdq, &cmd, sizeof(cmd));
|
||||
ret = riscv_iommu_queue_send(&iommu->cmdq, &cmd, sizeof(cmd), &prod);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
if (!timeout_us)
|
||||
return;
|
||||
|
|
@ -1560,6 +1582,7 @@ int riscv_iommu_init(struct riscv_iommu_device *iommu)
|
|||
int rc;
|
||||
|
||||
RISCV_IOMMU_QUEUE_INIT(&iommu->cmdq, CQ);
|
||||
raw_spin_lock_init(&iommu->cmdq.lock);
|
||||
RISCV_IOMMU_QUEUE_INIT(&iommu->fltq, FQ);
|
||||
|
||||
rc = riscv_iommu_init_check(iommu);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#define _RISCV_IOMMU_H_
|
||||
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
|
|
@ -23,6 +24,7 @@ struct riscv_iommu_queue {
|
|||
atomic_t prod; /* unbounded producer allocation index */
|
||||
atomic_t head; /* unbounded shadow ring buffer consumer index */
|
||||
atomic_t tail; /* unbounded shadow ring buffer producer index */
|
||||
raw_spinlock_t lock; /* serialize queue publishing */
|
||||
unsigned int mask; /* index mask, queue length - 1 */
|
||||
unsigned int irq; /* allocated interrupt number */
|
||||
struct riscv_iommu_device *iommu; /* iommu device handling the queue when active */
|
||||
|
|
|
|||
|
|
@ -974,6 +974,8 @@ static unsigned long *get_rto_from_iova(struct s390_domain *domain,
|
|||
case ZPCI_TABLE_TYPE_RFX:
|
||||
case ZPCI_TABLE_TYPE_RSX:
|
||||
rso = get_rso_from_iova(domain, iova);
|
||||
if (!rso)
|
||||
return NULL;
|
||||
rsx = calc_rsx(iova);
|
||||
rse = READ_ONCE(rso[rsx]);
|
||||
if (!reg_entry_isvalid(rse))
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user