diff options
Diffstat (limited to 'arch/s390/pci/pci_dma.c')
-rw-r--r-- | arch/s390/pci/pci_dma.c | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c index ebc9a49523aa..93223bd110c3 100644 --- a/arch/s390/pci/pci_dma.c +++ b/arch/s390/pci/pci_dma.c @@ -487,18 +487,18 @@ static int s390_dma_map_sg(struct device *dev, struct scatterlist *sg, unsigned int max = dma_get_max_seg_size(dev); unsigned int size = s->offset + s->length; unsigned int offset = s->offset; - int count = 0, i; + int count = 0, i, ret; for (i = 1; i < nr_elements; i++) { s = sg_next(s); - s->dma_address = DMA_MAPPING_ERROR; s->dma_length = 0; if (s->offset || (size & ~PAGE_MASK) || size + s->length > max) { - if (__s390_dma_map_sg(dev, start, size, - &dma->dma_address, dir)) + ret = __s390_dma_map_sg(dev, start, size, + &dma->dma_address, dir); + if (ret) goto unmap; dma->dma_address += offset; @@ -511,7 +511,8 @@ static int s390_dma_map_sg(struct device *dev, struct scatterlist *sg, } size += s->length; } - if (__s390_dma_map_sg(dev, start, size, &dma->dma_address, dir)) + ret = __s390_dma_map_sg(dev, start, size, &dma->dma_address, dir); + if (ret) goto unmap; dma->dma_address += offset; @@ -523,7 +524,7 @@ unmap: s390_dma_unmap_pages(dev, sg_dma_address(s), sg_dma_len(s), dir, attrs); - return 0; + return ret; } static void s390_dma_unmap_sg(struct device *dev, struct scatterlist *sg, @@ -590,10 +591,11 @@ int zpci_dma_init_device(struct zpci_dev *zdev) } } - rc = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma, - (u64) zdev->dma_table); - if (rc) + if (zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma, + (u64)zdev->dma_table)) { + rc = -EIO; goto free_bitmap; + } return 0; free_bitmap: @@ -608,17 +610,25 @@ out: return rc; } -void zpci_dma_exit_device(struct zpci_dev *zdev) +int zpci_dma_exit_device(struct zpci_dev *zdev) { + int cc = 0; + /* * At this point, if the device is part of an IOMMU domain, this would * be a strong hint towards a bug in the IOMMU API (common) code and/or * simultaneous access via IOMMU and DMA API. So let's issue a warning. */ WARN_ON(zdev->s390_domain); - - if (zpci_unregister_ioat(zdev, 0)) - return; + if (zdev_enabled(zdev)) + cc = zpci_unregister_ioat(zdev, 0); + /* + * cc == 3 indicates the function is gone already. This can happen + * if the function was deconfigured/disabled suddenly and we have not + * received a new handle yet. + */ + if (cc && cc != 3) + return -EIO; dma_cleanup_tables(zdev->dma_table); zdev->dma_table = NULL; @@ -626,8 +636,8 @@ void zpci_dma_exit_device(struct zpci_dev *zdev) zdev->iommu_bitmap = NULL; vfree(zdev->lazy_bitmap); zdev->lazy_bitmap = NULL; - zdev->next_bit = 0; + return 0; } static int __init dma_alloc_cpu_table_caches(void) |