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:
parent
4951eb2623
commit
d3b8282521
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue