Merge tag 'locks-v4.9-1' of git://git.samba.org/jlayton/linux
[cascardo/linux.git] / drivers / iommu / amd_iommu.c
index a8e4c5a..4025291 100644 (file)
@@ -105,6 +105,9 @@ struct flush_queue {
 
 DEFINE_PER_CPU(struct flush_queue, flush_queue);
 
+static atomic_t queue_timer_on;
+static struct timer_list queue_timer;
+
 /*
  * Domain for untranslated devices - only allocated
  * if iommu=pt passed on kernel cmd line.
@@ -228,6 +231,12 @@ static struct protection_domain *to_pdomain(struct iommu_domain *dom)
        return container_of(dom, struct protection_domain, domain);
 }
 
+static struct dma_ops_domain* to_dma_ops_domain(struct protection_domain *domain)
+{
+       BUG_ON(domain->flags != PD_DMA_OPS_MASK);
+       return container_of(domain, struct dma_ops_domain, domain);
+}
+
 static struct iommu_dev_data *alloc_dev_data(u16 devid)
 {
        struct iommu_dev_data *dev_data;
@@ -931,15 +940,13 @@ static void build_inv_irt(struct iommu_cmd *cmd, u16 devid)
  * Writes the command to the IOMMUs command buffer and informs the
  * hardware about the new command.
  */
-static int iommu_queue_command_sync(struct amd_iommu *iommu,
-                                   struct iommu_cmd *cmd,
-                                   bool sync)
+static int __iommu_queue_command_sync(struct amd_iommu *iommu,
+                                     struct iommu_cmd *cmd,
+                                     bool sync)
 {
        u32 left, tail, head, next_tail;
-       unsigned long flags;
 
 again:
-       spin_lock_irqsave(&iommu->lock, flags);
 
        head      = readl(iommu->mmio_base + MMIO_CMD_HEAD_OFFSET);
        tail      = readl(iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
@@ -948,15 +955,14 @@ again:
 
        if (left <= 2) {
                struct iommu_cmd sync_cmd;
-               volatile u64 sem = 0;
                int ret;
 
-               build_completion_wait(&sync_cmd, (u64)&sem);
-               copy_cmd_to_buffer(iommu, &sync_cmd, tail);
+               iommu->cmd_sem = 0;
 
-               spin_unlock_irqrestore(&iommu->lock, flags);
+               build_completion_wait(&sync_cmd, (u64)&iommu->cmd_sem);
+               copy_cmd_to_buffer(iommu, &sync_cmd, tail);
 
-               if ((ret = wait_on_sem(&sem)) != 0)
+               if ((ret = wait_on_sem(&iommu->cmd_sem)) != 0)
                        return ret;
 
                goto again;
@@ -967,9 +973,21 @@ again:
        /* We need to sync now to make sure all commands are processed */
        iommu->need_sync = sync;
 
+       return 0;
+}
+
+static int iommu_queue_command_sync(struct amd_iommu *iommu,
+                                   struct iommu_cmd *cmd,
+                                   bool sync)
+{
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&iommu->lock, flags);
+       ret = __iommu_queue_command_sync(iommu, cmd, sync);
        spin_unlock_irqrestore(&iommu->lock, flags);
 
-       return 0;
+       return ret;
 }
 
 static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
@@ -984,19 +1002,29 @@ static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
 static int iommu_completion_wait(struct amd_iommu *iommu)
 {
        struct iommu_cmd cmd;
-       volatile u64 sem = 0;
+       unsigned long flags;
        int ret;
 
        if (!iommu->need_sync)
                return 0;
 
-       build_completion_wait(&cmd, (u64)&sem);
 
-       ret = iommu_queue_command_sync(iommu, &cmd, false);
+       build_completion_wait(&cmd, (u64)&iommu->cmd_sem);
+
+       spin_lock_irqsave(&iommu->lock, flags);
+
+       iommu->cmd_sem = 0;
+
+       ret = __iommu_queue_command_sync(iommu, &cmd, false);
        if (ret)
-               return ret;
+               goto out_unlock;
+
+       ret = wait_on_sem(&iommu->cmd_sem);
 
-       return wait_on_sem(&sem);
+out_unlock:
+       spin_unlock_irqrestore(&iommu->lock, flags);
+
+       return ret;
 }
 
 static int iommu_flush_dte(struct amd_iommu *iommu, u16 devid)
@@ -1664,10 +1692,9 @@ static struct dma_ops_domain *dma_ops_domain_alloc(void)
        if (protection_domain_init(&dma_dom->domain))
                goto free_dma_dom;
 
-       dma_dom->domain.mode = PAGE_MODE_2_LEVEL;
+       dma_dom->domain.mode = PAGE_MODE_3_LEVEL;
        dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL);
        dma_dom->domain.flags = PD_DMA_OPS_MASK;
-       dma_dom->domain.priv = dma_dom;
        if (!dma_dom->domain.pt_root)
                goto free_dma_dom;
 
@@ -2151,6 +2178,28 @@ static void __queue_flush(struct flush_queue *queue)
        queue->next = 0;
 }
 
+static void queue_flush_all(void)
+{
+       int cpu;
+
+       for_each_possible_cpu(cpu) {
+               struct flush_queue *queue;
+               unsigned long flags;
+
+               queue = per_cpu_ptr(&flush_queue, cpu);
+               spin_lock_irqsave(&queue->lock, flags);
+               if (queue->next > 0)
+                       __queue_flush(queue);
+               spin_unlock_irqrestore(&queue->lock, flags);
+       }
+}
+
+static void queue_flush_timeout(unsigned long unsused)
+{
+       atomic_set(&queue_timer_on, 0);
+       queue_flush_all();
+}
+
 static void queue_add(struct dma_ops_domain *dma_dom,
                      unsigned long address, unsigned long pages)
 {
@@ -2176,6 +2225,10 @@ static void queue_add(struct dma_ops_domain *dma_dom,
        entry->dma_dom  = dma_dom;
 
        spin_unlock_irqrestore(&queue->lock, flags);
+
+       if (atomic_cmpxchg(&queue_timer_on, 0, 1) == 0)
+               mod_timer(&queue_timer, jiffies + msecs_to_jiffies(10));
+
        put_cpu_ptr(&flush_queue);
 }
 
@@ -2190,16 +2243,11 @@ static void queue_add(struct dma_ops_domain *dma_dom,
 static struct protection_domain *get_domain(struct device *dev)
 {
        struct protection_domain *domain;
-       struct iommu_domain *io_domain;
 
        if (!check_device(dev))
                return ERR_PTR(-EINVAL);
 
-       io_domain = iommu_get_domain_for_dev(dev);
-       if (!io_domain)
-               return NULL;
-
-       domain = to_pdomain(io_domain);
+       domain = get_dev_data(dev)->domain;
        if (!dma_ops_domain(domain))
                return ERR_PTR(-EBUSY);
 
@@ -2210,8 +2258,15 @@ static void update_device_table(struct protection_domain *domain)
 {
        struct iommu_dev_data *dev_data;
 
-       list_for_each_entry(dev_data, &domain->dev_list, list)
+       list_for_each_entry(dev_data, &domain->dev_list, list) {
                set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled);
+
+               if (dev_data->devid == dev_data->alias)
+                       continue;
+
+               /* There is an alias, update device table entry for it */
+               set_dte_entry(dev_data->alias, domain, dev_data->ats.enabled);
+       }
 }
 
 static void update_domain(struct protection_domain *domain)
@@ -2227,6 +2282,17 @@ static void update_domain(struct protection_domain *domain)
        domain->updated = false;
 }
 
+static int dir2prot(enum dma_data_direction direction)
+{
+       if (direction == DMA_TO_DEVICE)
+               return IOMMU_PROT_IR;
+       else if (direction == DMA_FROM_DEVICE)
+               return IOMMU_PROT_IW;
+       else if (direction == DMA_BIDIRECTIONAL)
+               return IOMMU_PROT_IW | IOMMU_PROT_IR;
+       else
+               return 0;
+}
 /*
  * This function contains common code for mapping of a physically
  * contiguous memory region into DMA address space. It is used by all
@@ -2237,7 +2303,7 @@ static dma_addr_t __map_single(struct device *dev,
                               struct dma_ops_domain *dma_dom,
                               phys_addr_t paddr,
                               size_t size,
-                              int direction,
+                              enum dma_data_direction direction,
                               u64 dma_mask)
 {
        dma_addr_t offset = paddr & ~PAGE_MASK;
@@ -2253,12 +2319,7 @@ static dma_addr_t __map_single(struct device *dev,
        if (address == DMA_ERROR_CODE)
                goto out;
 
-       if (direction == DMA_TO_DEVICE)
-               prot = IOMMU_PROT_IR;
-       else if (direction == DMA_FROM_DEVICE)
-               prot = IOMMU_PROT_IW;
-       else if (direction == DMA_BIDIRECTIONAL)
-               prot = IOMMU_PROT_IW | IOMMU_PROT_IR;
+       prot = dir2prot(direction);
 
        start = address;
        for (i = 0; i < pages; ++i) {
@@ -2333,10 +2394,11 @@ static void __unmap_single(struct dma_ops_domain *dma_dom,
 static dma_addr_t map_page(struct device *dev, struct page *page,
                           unsigned long offset, size_t size,
                           enum dma_data_direction dir,
-                          struct dma_attrs *attrs)
+                          unsigned long attrs)
 {
        phys_addr_t paddr = page_to_phys(page) + offset;
        struct protection_domain *domain;
+       struct dma_ops_domain *dma_dom;
        u64 dma_mask;
 
        domain = get_domain(dev);
@@ -2346,23 +2408,53 @@ static dma_addr_t map_page(struct device *dev, struct page *page,
                return DMA_ERROR_CODE;
 
        dma_mask = *dev->dma_mask;
+       dma_dom = to_dma_ops_domain(domain);
 
-       return __map_single(dev, domain->priv, paddr, size, dir, dma_mask);
+       return __map_single(dev, dma_dom, paddr, size, dir, dma_mask);
 }
 
 /*
  * The exported unmap_single function for dma_ops.
  */
 static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
-                      enum dma_data_direction dir, struct dma_attrs *attrs)
+                      enum dma_data_direction dir, unsigned long attrs)
 {
        struct protection_domain *domain;
+       struct dma_ops_domain *dma_dom;
 
        domain = get_domain(dev);
        if (IS_ERR(domain))
                return;
 
-       __unmap_single(domain->priv, dma_addr, size, dir);
+       dma_dom = to_dma_ops_domain(domain);
+
+       __unmap_single(dma_dom, dma_addr, size, dir);
+}
+
+static int sg_num_pages(struct device *dev,
+                       struct scatterlist *sglist,
+                       int nelems)
+{
+       unsigned long mask, boundary_size;
+       struct scatterlist *s;
+       int i, npages = 0;
+
+       mask          = dma_get_seg_boundary(dev);
+       boundary_size = mask + 1 ? ALIGN(mask + 1, PAGE_SIZE) >> PAGE_SHIFT :
+                                  1UL << (BITS_PER_LONG - PAGE_SHIFT);
+
+       for_each_sg(sglist, s, nelems, i) {
+               int p, n;
+
+               s->dma_address = npages << PAGE_SHIFT;
+               p = npages % boundary_size;
+               n = iommu_num_pages(sg_phys(s), s->length, PAGE_SIZE);
+               if (p + n > boundary_size)
+                       npages += boundary_size - p;
+               npages += n;
+       }
+
+       return npages;
 }
 
 /*
@@ -2370,45 +2462,79 @@ static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
  * lists).
  */
 static int map_sg(struct device *dev, struct scatterlist *sglist,
-                 int nelems, enum dma_data_direction dir,
-                 struct dma_attrs *attrs)
+                 int nelems, enum dma_data_direction direction,
+                 unsigned long attrs)
 {
+       int mapped_pages = 0, npages = 0, prot = 0, i;
        struct protection_domain *domain;
-       int i;
+       struct dma_ops_domain *dma_dom;
        struct scatterlist *s;
-       phys_addr_t paddr;
-       int mapped_elems = 0;
+       unsigned long address;
        u64 dma_mask;
 
        domain = get_domain(dev);
        if (IS_ERR(domain))
                return 0;
 
+       dma_dom  = to_dma_ops_domain(domain);
        dma_mask = *dev->dma_mask;
 
+       npages = sg_num_pages(dev, sglist, nelems);
+
+       address = dma_ops_alloc_iova(dev, dma_dom, npages, dma_mask);
+       if (address == DMA_ERROR_CODE)
+               goto out_err;
+
+       prot = dir2prot(direction);
+
+       /* Map all sg entries */
        for_each_sg(sglist, s, nelems, i) {
-               paddr = sg_phys(s);
+               int j, pages = iommu_num_pages(sg_phys(s), s->length, PAGE_SIZE);
+
+               for (j = 0; j < pages; ++j) {
+                       unsigned long bus_addr, phys_addr;
+                       int ret;
 
-               s->dma_address = __map_single(dev, domain->priv,
-                                             paddr, s->length, dir, dma_mask);
+                       bus_addr  = address + s->dma_address + (j << PAGE_SHIFT);
+                       phys_addr = (sg_phys(s) & PAGE_MASK) + (j << PAGE_SHIFT);
+                       ret = iommu_map_page(domain, bus_addr, phys_addr, PAGE_SIZE, prot, GFP_ATOMIC);
+                       if (ret)
+                               goto out_unmap;
 
-               if (s->dma_address) {
-                       s->dma_length = s->length;
-                       mapped_elems++;
-               } else
-                       goto unmap;
+                       mapped_pages += 1;
+               }
+       }
+
+       /* Everything is mapped - write the right values into s->dma_address */
+       for_each_sg(sglist, s, nelems, i) {
+               s->dma_address += address + s->offset;
+               s->dma_length   = s->length;
        }
 
-       return mapped_elems;
+       return nelems;
+
+out_unmap:
+       pr_err("%s: IOMMU mapping error in map_sg (io-pages: %d)\n",
+              dev_name(dev), npages);
+
+       for_each_sg(sglist, s, nelems, i) {
+               int j, pages = iommu_num_pages(sg_phys(s), s->length, PAGE_SIZE);
 
-unmap:
-       for_each_sg(sglist, s, mapped_elems, i) {
-               if (s->dma_address)
-                       __unmap_single(domain->priv, s->dma_address,
-                                      s->dma_length, dir);
-               s->dma_address = s->dma_length = 0;
+               for (j = 0; j < pages; ++j) {
+                       unsigned long bus_addr;
+
+                       bus_addr  = address + s->dma_address + (j << PAGE_SHIFT);
+                       iommu_unmap_page(domain, bus_addr, PAGE_SIZE);
+
+                       if (--mapped_pages)
+                               goto out_free_iova;
+               }
        }
 
+out_free_iova:
+       free_iova_fast(&dma_dom->iovad, address, npages);
+
+out_err:
        return 0;
 }
 
@@ -2418,21 +2544,22 @@ unmap:
  */
 static void unmap_sg(struct device *dev, struct scatterlist *sglist,
                     int nelems, enum dma_data_direction dir,
-                    struct dma_attrs *attrs)
+                    unsigned long attrs)
 {
        struct protection_domain *domain;
-       struct scatterlist *s;
-       int i;
+       struct dma_ops_domain *dma_dom;
+       unsigned long startaddr;
+       int npages = 2;
 
        domain = get_domain(dev);
        if (IS_ERR(domain))
                return;
 
-       for_each_sg(sglist, s, nelems, i) {
-               __unmap_single(domain->priv, s->dma_address,
-                              s->dma_length, dir);
-               s->dma_address = s->dma_length = 0;
-       }
+       startaddr = sg_dma_address(sglist) & PAGE_MASK;
+       dma_dom   = to_dma_ops_domain(domain);
+       npages    = sg_num_pages(dev, sglist, nelems);
+
+       __unmap_single(dma_dom, startaddr, npages << PAGE_SHIFT, dir);
 }
 
 /*
@@ -2440,10 +2567,11 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
  */
 static void *alloc_coherent(struct device *dev, size_t size,
                            dma_addr_t *dma_addr, gfp_t flag,
-                           struct dma_attrs *attrs)
+                           unsigned long attrs)
 {
        u64 dma_mask = dev->coherent_dma_mask;
        struct protection_domain *domain;
+       struct dma_ops_domain *dma_dom;
        struct page *page;
 
        domain = get_domain(dev);
@@ -2454,6 +2582,7 @@ static void *alloc_coherent(struct device *dev, size_t size,
        } else if (IS_ERR(domain))
                return NULL;
 
+       dma_dom   = to_dma_ops_domain(domain);
        size      = PAGE_ALIGN(size);
        dma_mask  = dev->coherent_dma_mask;
        flag     &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
@@ -2473,7 +2602,7 @@ static void *alloc_coherent(struct device *dev, size_t size,
        if (!dma_mask)
                dma_mask = *dev->dma_mask;
 
-       *dma_addr = __map_single(dev, domain->priv, page_to_phys(page),
+       *dma_addr = __map_single(dev, dma_dom, page_to_phys(page),
                                 size, DMA_BIDIRECTIONAL, dma_mask);
 
        if (*dma_addr == DMA_ERROR_CODE)
@@ -2494,9 +2623,10 @@ out_free:
  */
 static void free_coherent(struct device *dev, size_t size,
                          void *virt_addr, dma_addr_t dma_addr,
-                         struct dma_attrs *attrs)
+                         unsigned long attrs)
 {
        struct protection_domain *domain;
+       struct dma_ops_domain *dma_dom;
        struct page *page;
 
        page = virt_to_page(virt_addr);
@@ -2506,7 +2636,9 @@ static void free_coherent(struct device *dev, size_t size,
        if (IS_ERR(domain))
                goto free_mem;
 
-       __unmap_single(domain->priv, dma_addr, size, DMA_BIDIRECTIONAL);
+       dma_dom = to_dma_ops_domain(domain);
+
+       __unmap_single(dma_dom, dma_addr, size, DMA_BIDIRECTIONAL);
 
 free_mem:
        if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
@@ -2634,6 +2766,9 @@ out_put_iova:
 
 int __init amd_iommu_init_dma_ops(void)
 {
+       setup_timer(&queue_timer, queue_flush_timeout, 0);
+       atomic_set(&queue_timer_on, 0);
+
        swiotlb        = iommu_pass_through ? 1 : 0;
        iommu_detected = 1;
 
@@ -2775,9 +2910,7 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
 static void amd_iommu_domain_free(struct iommu_domain *dom)
 {
        struct protection_domain *domain;
-
-       if (!dom)
-               return;
+       struct dma_ops_domain *dma_dom;
 
        domain = to_pdomain(dom);
 
@@ -2786,13 +2919,31 @@ static void amd_iommu_domain_free(struct iommu_domain *dom)
 
        BUG_ON(domain->dev_cnt != 0);
 
-       if (domain->mode != PAGE_MODE_NONE)
-               free_pagetable(domain);
+       if (!dom)
+               return;
 
-       if (domain->flags & PD_IOMMUV2_MASK)
-               free_gcr3_table(domain);
+       switch (dom->type) {
+       case IOMMU_DOMAIN_DMA:
+               /*
+                * First make sure the domain is no longer referenced from the
+                * flush queue
+                */
+               queue_flush_all();
+
+               /* Now release the domain */
+               dma_dom = to_dma_ops_domain(domain);
+               dma_ops_domain_free(dma_dom);
+               break;
+       default:
+               if (domain->mode != PAGE_MODE_NONE)
+                       free_pagetable(domain);
 
-       protection_domain_free(domain);
+               if (domain->flags & PD_IOMMUV2_MASK)
+                       free_gcr3_table(domain);
+
+               protection_domain_free(domain);
+               break;
+       }
 }
 
 static void amd_iommu_detach_device(struct iommu_domain *dom,
@@ -2968,8 +3119,7 @@ static void amd_iommu_apply_dm_region(struct device *dev,
                                      struct iommu_domain *domain,
                                      struct iommu_dm_region *region)
 {
-       struct protection_domain *pdomain = to_pdomain(domain);
-       struct dma_ops_domain *dma_dom = pdomain->priv;
+       struct dma_ops_domain *dma_dom = to_dma_ops_domain(to_pdomain(domain));
        unsigned long start, end;
 
        start = IOVA_PFN(region->start);