mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
iommu/s390: support cleanup of additional table regions
Extend the existing dma_cleanup_tables to also handle region second and region first tables. Reviewed-by: Niklas Schnelle <schnelle@linux.ibm.com> Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com> Tested-by: Niklas Schnelle <schnelle@linux.ibm.com> Link: https://lore.kernel.org/r/20250411202433.181683-3-mjrosato@linux.ibm.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
83c1aec210
commit
a2392b8f1f
|
|
@ -121,6 +121,22 @@ static inline int pt_entry_isvalid(unsigned long entry)
|
|||
return (entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID;
|
||||
}
|
||||
|
||||
static inline unsigned long *get_rf_rso(unsigned long entry)
|
||||
{
|
||||
if ((entry & ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_RFX)
|
||||
return phys_to_virt(entry & ZPCI_RTE_ADDR_MASK);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline unsigned long *get_rs_rto(unsigned long entry)
|
||||
{
|
||||
if ((entry & ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_RSX)
|
||||
return phys_to_virt(entry & ZPCI_RTE_ADDR_MASK);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline unsigned long *get_rt_sto(unsigned long entry)
|
||||
{
|
||||
if ((entry & ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_RTX)
|
||||
|
|
@ -192,18 +208,59 @@ static void dma_free_seg_table(unsigned long entry)
|
|||
dma_free_cpu_table(sto);
|
||||
}
|
||||
|
||||
static void dma_cleanup_tables(unsigned long *table)
|
||||
static void dma_free_rt_table(unsigned long entry)
|
||||
{
|
||||
unsigned long *rto = get_rs_rto(entry);
|
||||
int rtx;
|
||||
|
||||
if (!table)
|
||||
for (rtx = 0; rtx < ZPCI_TABLE_ENTRIES; rtx++)
|
||||
if (reg_entry_isvalid(rto[rtx]))
|
||||
dma_free_seg_table(rto[rtx]);
|
||||
|
||||
dma_free_cpu_table(rto);
|
||||
}
|
||||
|
||||
static void dma_free_rs_table(unsigned long entry)
|
||||
{
|
||||
unsigned long *rso = get_rf_rso(entry);
|
||||
int rsx;
|
||||
|
||||
for (rsx = 0; rsx < ZPCI_TABLE_ENTRIES; rsx++)
|
||||
if (reg_entry_isvalid(rso[rsx]))
|
||||
dma_free_rt_table(rso[rsx]);
|
||||
|
||||
dma_free_cpu_table(rso);
|
||||
}
|
||||
|
||||
static void dma_cleanup_tables(struct s390_domain *domain)
|
||||
{
|
||||
int rtx, rsx, rfx;
|
||||
|
||||
if (!domain->dma_table)
|
||||
return;
|
||||
|
||||
for (rtx = 0; rtx < ZPCI_TABLE_ENTRIES; rtx++)
|
||||
if (reg_entry_isvalid(table[rtx]))
|
||||
dma_free_seg_table(table[rtx]);
|
||||
switch (domain->origin_type) {
|
||||
case ZPCI_TABLE_TYPE_RFX:
|
||||
for (rfx = 0; rfx < ZPCI_TABLE_ENTRIES; rfx++)
|
||||
if (reg_entry_isvalid(domain->dma_table[rfx]))
|
||||
dma_free_rs_table(domain->dma_table[rfx]);
|
||||
break;
|
||||
case ZPCI_TABLE_TYPE_RSX:
|
||||
for (rsx = 0; rsx < ZPCI_TABLE_ENTRIES; rsx++)
|
||||
if (reg_entry_isvalid(domain->dma_table[rsx]))
|
||||
dma_free_rt_table(domain->dma_table[rsx]);
|
||||
break;
|
||||
case ZPCI_TABLE_TYPE_RTX:
|
||||
for (rtx = 0; rtx < ZPCI_TABLE_ENTRIES; rtx++)
|
||||
if (reg_entry_isvalid(domain->dma_table[rtx]))
|
||||
dma_free_seg_table(domain->dma_table[rtx]);
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(1, "Invalid IOMMU table (%x)\n", domain->origin_type);
|
||||
return;
|
||||
}
|
||||
|
||||
dma_free_cpu_table(table);
|
||||
dma_free_cpu_table(domain->dma_table);
|
||||
}
|
||||
|
||||
static unsigned long *dma_alloc_page_table(gfp_t gfp)
|
||||
|
|
@ -358,7 +415,7 @@ static void s390_iommu_rcu_free_domain(struct rcu_head *head)
|
|||
{
|
||||
struct s390_domain *s390_domain = container_of(head, struct s390_domain, rcu);
|
||||
|
||||
dma_cleanup_tables(s390_domain->dma_table);
|
||||
dma_cleanup_tables(s390_domain);
|
||||
kfree(s390_domain);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user