mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
iommu/s390: support iova_to_phys for additional table regions
The origin_type of the dma_table is used to determine how many table levels must be traversed for the translation. 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-4-mjrosato@linux.ibm.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
a2392b8f1f
commit
1fe3f3cad5
|
|
@ -55,6 +55,8 @@ enum zpci_ioat_dtype {
|
|||
#define ZPCI_PT_BITS 8
|
||||
#define ZPCI_ST_SHIFT (ZPCI_PT_BITS + PAGE_SHIFT)
|
||||
#define ZPCI_RT_SHIFT (ZPCI_ST_SHIFT + ZPCI_TABLE_BITS)
|
||||
#define ZPCI_RS_SHIFT (ZPCI_RT_SHIFT + ZPCI_TABLE_BITS)
|
||||
#define ZPCI_RF_SHIFT (ZPCI_RS_SHIFT + ZPCI_TABLE_BITS)
|
||||
|
||||
#define ZPCI_RTE_FLAG_MASK 0x3fffUL
|
||||
#define ZPCI_RTE_ADDR_MASK (~ZPCI_RTE_FLAG_MASK)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,16 @@ struct s390_domain {
|
|||
|
||||
static struct iommu_domain blocking_domain;
|
||||
|
||||
static inline unsigned int calc_rfx(dma_addr_t ptr)
|
||||
{
|
||||
return ((unsigned long)ptr >> ZPCI_RF_SHIFT) & ZPCI_INDEX_MASK;
|
||||
}
|
||||
|
||||
static inline unsigned int calc_rsx(dma_addr_t ptr)
|
||||
{
|
||||
return ((unsigned long)ptr >> ZPCI_RS_SHIFT) & ZPCI_INDEX_MASK;
|
||||
}
|
||||
|
||||
static inline unsigned int calc_rtx(dma_addr_t ptr)
|
||||
{
|
||||
return ((unsigned long)ptr >> ZPCI_RT_SHIFT) & ZPCI_INDEX_MASK;
|
||||
|
|
@ -759,6 +769,51 @@ static int s390_iommu_map_pages(struct iommu_domain *domain,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static unsigned long *get_rso_from_iova(struct s390_domain *domain,
|
||||
dma_addr_t iova)
|
||||
{
|
||||
unsigned long *rfo;
|
||||
unsigned long rfe;
|
||||
unsigned int rfx;
|
||||
|
||||
switch (domain->origin_type) {
|
||||
case ZPCI_TABLE_TYPE_RFX:
|
||||
rfo = domain->dma_table;
|
||||
rfx = calc_rfx(iova);
|
||||
rfe = READ_ONCE(rfo[rfx]);
|
||||
if (!reg_entry_isvalid(rfe))
|
||||
return NULL;
|
||||
return get_rf_rso(rfe);
|
||||
case ZPCI_TABLE_TYPE_RSX:
|
||||
return domain->dma_table;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long *get_rto_from_iova(struct s390_domain *domain,
|
||||
dma_addr_t iova)
|
||||
{
|
||||
unsigned long *rso;
|
||||
unsigned long rse;
|
||||
unsigned int rsx;
|
||||
|
||||
switch (domain->origin_type) {
|
||||
case ZPCI_TABLE_TYPE_RFX:
|
||||
case ZPCI_TABLE_TYPE_RSX:
|
||||
rso = get_rso_from_iova(domain, iova);
|
||||
rsx = calc_rsx(iova);
|
||||
rse = READ_ONCE(rso[rsx]);
|
||||
if (!reg_entry_isvalid(rse))
|
||||
return NULL;
|
||||
return get_rs_rto(rse);
|
||||
case ZPCI_TABLE_TYPE_RTX:
|
||||
return domain->dma_table;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static phys_addr_t s390_iommu_iova_to_phys(struct iommu_domain *domain,
|
||||
dma_addr_t iova)
|
||||
{
|
||||
|
|
@ -772,10 +827,13 @@ static phys_addr_t s390_iommu_iova_to_phys(struct iommu_domain *domain,
|
|||
iova > domain->geometry.aperture_end)
|
||||
return 0;
|
||||
|
||||
rto = get_rto_from_iova(s390_domain, iova);
|
||||
if (!rto)
|
||||
return 0;
|
||||
|
||||
rtx = calc_rtx(iova);
|
||||
sx = calc_sx(iova);
|
||||
px = calc_px(iova);
|
||||
rto = s390_domain->dma_table;
|
||||
|
||||
rte = READ_ONCE(rto[rtx]);
|
||||
if (reg_entry_isvalid(rte)) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user