iommu/s390: Push the gfp parameter to the kmem_cache_alloc()'s

dma_alloc_cpu_table() and dma_alloc_page_table() are eventually called by
iommufd through s390_iommu_map_pages() and it should not be forced to
atomic. Thread the gfp parameter through the call chain starting from
s390_iommu_map_pages().

Reviewed-by: Niklas Schnelle <schnelle@linux.ibm.com>
Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/r/9-v3-76b587fe28df+6e3-iommu_map_gfp_jgg@nvidia.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
Jason Gunthorpe 2023-01-23 16:36:02 -04:00 committed by Joerg Roedel
parent 4951eb2623
commit d3b8282521
3 changed files with 29 additions and 22 deletions

View File

@ -186,9 +186,10 @@ static inline unsigned long *get_st_pto(unsigned long entry)
/* Prototypes */ /* Prototypes */
void dma_free_seg_table(unsigned long); void dma_free_seg_table(unsigned long);
unsigned long *dma_alloc_cpu_table(void); unsigned long *dma_alloc_cpu_table(gfp_t gfp);
void dma_cleanup_tables(unsigned long *); void dma_cleanup_tables(unsigned long *);
unsigned long *dma_walk_cpu_trans(unsigned long *rto, dma_addr_t dma_addr); unsigned long *dma_walk_cpu_trans(unsigned long *rto, dma_addr_t dma_addr,
gfp_t gfp);
void dma_update_cpu_trans(unsigned long *entry, phys_addr_t page_addr, int flags); void dma_update_cpu_trans(unsigned long *entry, phys_addr_t page_addr, int flags);
extern const struct dma_map_ops s390_pci_dma_ops; extern const struct dma_map_ops s390_pci_dma_ops;

View File

@ -27,11 +27,11 @@ static int zpci_refresh_global(struct zpci_dev *zdev)
zdev->iommu_pages * PAGE_SIZE); zdev->iommu_pages * PAGE_SIZE);
} }
unsigned long *dma_alloc_cpu_table(void) unsigned long *dma_alloc_cpu_table(gfp_t gfp)
{ {
unsigned long *table, *entry; unsigned long *table, *entry;
table = kmem_cache_alloc(dma_region_table_cache, GFP_ATOMIC); table = kmem_cache_alloc(dma_region_table_cache, gfp);
if (!table) if (!table)
return NULL; return NULL;
@ -45,11 +45,11 @@ static void dma_free_cpu_table(void *table)
kmem_cache_free(dma_region_table_cache, table); kmem_cache_free(dma_region_table_cache, table);
} }
static unsigned long *dma_alloc_page_table(void) static unsigned long *dma_alloc_page_table(gfp_t gfp)
{ {
unsigned long *table, *entry; unsigned long *table, *entry;
table = kmem_cache_alloc(dma_page_table_cache, GFP_ATOMIC); table = kmem_cache_alloc(dma_page_table_cache, gfp);
if (!table) if (!table)
return NULL; return NULL;
@ -63,7 +63,7 @@ static void dma_free_page_table(void *table)
kmem_cache_free(dma_page_table_cache, table); kmem_cache_free(dma_page_table_cache, table);
} }
static unsigned long *dma_get_seg_table_origin(unsigned long *rtep) static unsigned long *dma_get_seg_table_origin(unsigned long *rtep, gfp_t gfp)
{ {
unsigned long old_rte, rte; unsigned long old_rte, rte;
unsigned long *sto; unsigned long *sto;
@ -72,7 +72,7 @@ static unsigned long *dma_get_seg_table_origin(unsigned long *rtep)
if (reg_entry_isvalid(rte)) { if (reg_entry_isvalid(rte)) {
sto = get_rt_sto(rte); sto = get_rt_sto(rte);
} else { } else {
sto = dma_alloc_cpu_table(); sto = dma_alloc_cpu_table(gfp);
if (!sto) if (!sto)
return NULL; return NULL;
@ -90,7 +90,7 @@ static unsigned long *dma_get_seg_table_origin(unsigned long *rtep)
return sto; return sto;
} }
static unsigned long *dma_get_page_table_origin(unsigned long *step) static unsigned long *dma_get_page_table_origin(unsigned long *step, gfp_t gfp)
{ {
unsigned long old_ste, ste; unsigned long old_ste, ste;
unsigned long *pto; unsigned long *pto;
@ -99,7 +99,7 @@ static unsigned long *dma_get_page_table_origin(unsigned long *step)
if (reg_entry_isvalid(ste)) { if (reg_entry_isvalid(ste)) {
pto = get_st_pto(ste); pto = get_st_pto(ste);
} else { } else {
pto = dma_alloc_page_table(); pto = dma_alloc_page_table(gfp);
if (!pto) if (!pto)
return NULL; return NULL;
set_st_pto(&ste, virt_to_phys(pto)); set_st_pto(&ste, virt_to_phys(pto));
@ -116,18 +116,19 @@ static unsigned long *dma_get_page_table_origin(unsigned long *step)
return pto; return pto;
} }
unsigned long *dma_walk_cpu_trans(unsigned long *rto, dma_addr_t dma_addr) unsigned long *dma_walk_cpu_trans(unsigned long *rto, dma_addr_t dma_addr,
gfp_t gfp)
{ {
unsigned long *sto, *pto; unsigned long *sto, *pto;
unsigned int rtx, sx, px; unsigned int rtx, sx, px;
rtx = calc_rtx(dma_addr); rtx = calc_rtx(dma_addr);
sto = dma_get_seg_table_origin(&rto[rtx]); sto = dma_get_seg_table_origin(&rto[rtx], gfp);
if (!sto) if (!sto)
return NULL; return NULL;
sx = calc_sx(dma_addr); sx = calc_sx(dma_addr);
pto = dma_get_page_table_origin(&sto[sx]); pto = dma_get_page_table_origin(&sto[sx], gfp);
if (!pto) if (!pto)
return NULL; return NULL;
@ -170,7 +171,8 @@ static int __dma_update_trans(struct zpci_dev *zdev, phys_addr_t pa,
return -EINVAL; return -EINVAL;
for (i = 0; i < nr_pages; i++) { for (i = 0; i < nr_pages; i++) {
entry = dma_walk_cpu_trans(zdev->dma_table, dma_addr); entry = dma_walk_cpu_trans(zdev->dma_table, dma_addr,
GFP_ATOMIC);
if (!entry) { if (!entry) {
rc = -ENOMEM; rc = -ENOMEM;
goto undo_cpu_trans; goto undo_cpu_trans;
@ -186,7 +188,8 @@ undo_cpu_trans:
while (i-- > 0) { while (i-- > 0) {
page_addr -= PAGE_SIZE; page_addr -= PAGE_SIZE;
dma_addr -= PAGE_SIZE; dma_addr -= PAGE_SIZE;
entry = dma_walk_cpu_trans(zdev->dma_table, dma_addr); entry = dma_walk_cpu_trans(zdev->dma_table, dma_addr,
GFP_ATOMIC);
if (!entry) if (!entry)
break; break;
dma_update_cpu_trans(entry, page_addr, flags); dma_update_cpu_trans(entry, page_addr, flags);
@ -576,7 +579,7 @@ int zpci_dma_init_device(struct zpci_dev *zdev)
spin_lock_init(&zdev->iommu_bitmap_lock); spin_lock_init(&zdev->iommu_bitmap_lock);
zdev->dma_table = dma_alloc_cpu_table(); zdev->dma_table = dma_alloc_cpu_table(GFP_ATOMIC);
if (!zdev->dma_table) { if (!zdev->dma_table) {
rc = -ENOMEM; rc = -ENOMEM;
goto out; goto out;

View File

@ -52,7 +52,7 @@ static struct iommu_domain *s390_domain_alloc(unsigned domain_type)
if (!s390_domain) if (!s390_domain)
return NULL; return NULL;
s390_domain->dma_table = dma_alloc_cpu_table(); s390_domain->dma_table = dma_alloc_cpu_table(GFP_ATOMIC);
if (!s390_domain->dma_table) { if (!s390_domain->dma_table) {
kfree(s390_domain); kfree(s390_domain);
return NULL; return NULL;
@ -260,7 +260,8 @@ static void s390_iommu_iotlb_sync_map(struct iommu_domain *domain,
static int s390_iommu_validate_trans(struct s390_domain *s390_domain, static int s390_iommu_validate_trans(struct s390_domain *s390_domain,
phys_addr_t pa, dma_addr_t dma_addr, phys_addr_t pa, dma_addr_t dma_addr,
unsigned long nr_pages, int flags) unsigned long nr_pages, int flags,
gfp_t gfp)
{ {
phys_addr_t page_addr = pa & PAGE_MASK; phys_addr_t page_addr = pa & PAGE_MASK;
unsigned long *entry; unsigned long *entry;
@ -268,7 +269,8 @@ static int s390_iommu_validate_trans(struct s390_domain *s390_domain,
int rc; int rc;
for (i = 0; i < nr_pages; i++) { for (i = 0; i < nr_pages; i++) {
entry = dma_walk_cpu_trans(s390_domain->dma_table, dma_addr); entry = dma_walk_cpu_trans(s390_domain->dma_table, dma_addr,
gfp);
if (unlikely(!entry)) { if (unlikely(!entry)) {
rc = -ENOMEM; rc = -ENOMEM;
goto undo_cpu_trans; goto undo_cpu_trans;
@ -284,7 +286,7 @@ undo_cpu_trans:
while (i-- > 0) { while (i-- > 0) {
dma_addr -= PAGE_SIZE; dma_addr -= PAGE_SIZE;
entry = dma_walk_cpu_trans(s390_domain->dma_table, entry = dma_walk_cpu_trans(s390_domain->dma_table,
dma_addr); dma_addr, gfp);
if (!entry) if (!entry)
break; break;
dma_update_cpu_trans(entry, 0, ZPCI_PTE_INVALID); dma_update_cpu_trans(entry, 0, ZPCI_PTE_INVALID);
@ -301,7 +303,8 @@ static int s390_iommu_invalidate_trans(struct s390_domain *s390_domain,
int rc = 0; int rc = 0;
for (i = 0; i < nr_pages; i++) { for (i = 0; i < nr_pages; i++) {
entry = dma_walk_cpu_trans(s390_domain->dma_table, dma_addr); entry = dma_walk_cpu_trans(s390_domain->dma_table, dma_addr,
GFP_ATOMIC);
if (unlikely(!entry)) { if (unlikely(!entry)) {
rc = -EINVAL; rc = -EINVAL;
break; break;
@ -339,7 +342,7 @@ static int s390_iommu_map_pages(struct iommu_domain *domain,
flags |= ZPCI_TABLE_PROTECTED; flags |= ZPCI_TABLE_PROTECTED;
rc = s390_iommu_validate_trans(s390_domain, paddr, iova, rc = s390_iommu_validate_trans(s390_domain, paddr, iova,
pgcount, flags); pgcount, flags, gfp);
if (!rc) if (!rc)
*mapped = size; *mapped = size;