Skip to content

Commit 1fe3f3c

Browse files
rosatomjjoergroedel
authored andcommitted
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>
1 parent a2392b8 commit 1fe3f3c

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

arch/s390/include/asm/pci_dma.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ enum zpci_ioat_dtype {
5555
#define ZPCI_PT_BITS 8
5656
#define ZPCI_ST_SHIFT (ZPCI_PT_BITS + PAGE_SHIFT)
5757
#define ZPCI_RT_SHIFT (ZPCI_ST_SHIFT + ZPCI_TABLE_BITS)
58+
#define ZPCI_RS_SHIFT (ZPCI_RT_SHIFT + ZPCI_TABLE_BITS)
59+
#define ZPCI_RF_SHIFT (ZPCI_RS_SHIFT + ZPCI_TABLE_BITS)
5860

5961
#define ZPCI_RTE_FLAG_MASK 0x3fffUL
6062
#define ZPCI_RTE_ADDR_MASK (~ZPCI_RTE_FLAG_MASK)

drivers/iommu/s390-iommu.c

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ struct s390_domain {
3636

3737
static struct iommu_domain blocking_domain;
3838

39+
static inline unsigned int calc_rfx(dma_addr_t ptr)
40+
{
41+
return ((unsigned long)ptr >> ZPCI_RF_SHIFT) & ZPCI_INDEX_MASK;
42+
}
43+
44+
static inline unsigned int calc_rsx(dma_addr_t ptr)
45+
{
46+
return ((unsigned long)ptr >> ZPCI_RS_SHIFT) & ZPCI_INDEX_MASK;
47+
}
48+
3949
static inline unsigned int calc_rtx(dma_addr_t ptr)
4050
{
4151
return ((unsigned long)ptr >> ZPCI_RT_SHIFT) & ZPCI_INDEX_MASK;
@@ -759,6 +769,51 @@ static int s390_iommu_map_pages(struct iommu_domain *domain,
759769
return rc;
760770
}
761771

772+
static unsigned long *get_rso_from_iova(struct s390_domain *domain,
773+
dma_addr_t iova)
774+
{
775+
unsigned long *rfo;
776+
unsigned long rfe;
777+
unsigned int rfx;
778+
779+
switch (domain->origin_type) {
780+
case ZPCI_TABLE_TYPE_RFX:
781+
rfo = domain->dma_table;
782+
rfx = calc_rfx(iova);
783+
rfe = READ_ONCE(rfo[rfx]);
784+
if (!reg_entry_isvalid(rfe))
785+
return NULL;
786+
return get_rf_rso(rfe);
787+
case ZPCI_TABLE_TYPE_RSX:
788+
return domain->dma_table;
789+
default:
790+
return NULL;
791+
}
792+
}
793+
794+
static unsigned long *get_rto_from_iova(struct s390_domain *domain,
795+
dma_addr_t iova)
796+
{
797+
unsigned long *rso;
798+
unsigned long rse;
799+
unsigned int rsx;
800+
801+
switch (domain->origin_type) {
802+
case ZPCI_TABLE_TYPE_RFX:
803+
case ZPCI_TABLE_TYPE_RSX:
804+
rso = get_rso_from_iova(domain, iova);
805+
rsx = calc_rsx(iova);
806+
rse = READ_ONCE(rso[rsx]);
807+
if (!reg_entry_isvalid(rse))
808+
return NULL;
809+
return get_rs_rto(rse);
810+
case ZPCI_TABLE_TYPE_RTX:
811+
return domain->dma_table;
812+
default:
813+
return NULL;
814+
}
815+
}
816+
762817
static phys_addr_t s390_iommu_iova_to_phys(struct iommu_domain *domain,
763818
dma_addr_t iova)
764819
{
@@ -772,10 +827,13 @@ static phys_addr_t s390_iommu_iova_to_phys(struct iommu_domain *domain,
772827
iova > domain->geometry.aperture_end)
773828
return 0;
774829

830+
rto = get_rto_from_iova(s390_domain, iova);
831+
if (!rto)
832+
return 0;
833+
775834
rtx = calc_rtx(iova);
776835
sx = calc_sx(iova);
777836
px = calc_px(iova);
778-
rto = s390_domain->dma_table;
779837

780838
rte = READ_ONCE(rto[rtx]);
781839
if (reg_entry_isvalid(rte)) {

0 commit comments

Comments
 (0)