ALSA: usb-audio: fix feature unit parser for UAC2
[safe/jmp/linux-2.6] / drivers / pci / intel-iommu.c
index e3e84ca..371dc56 100644 (file)
@@ -305,7 +305,7 @@ struct device_domain_info {
        int segment;            /* PCI domain */
        u8 bus;                 /* PCI bus number */
        u8 devfn;               /* PCI devfn number */
-       struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */
+       struct pci_dev *dev; /* it's NULL for PCIe-to-PCI bridge */
        struct intel_iommu *iommu; /* IOMMU used by this device */
        struct dmar_domain *domain; /* pointer to domain */
 };
@@ -387,33 +387,14 @@ static struct kmem_cache *iommu_domain_cache;
 static struct kmem_cache *iommu_devinfo_cache;
 static struct kmem_cache *iommu_iova_cache;
 
-static inline void *iommu_kmem_cache_alloc(struct kmem_cache *cachep)
-{
-       unsigned int flags;
-       void *vaddr;
-
-       /* trying to avoid low memory issues */
-       flags = current->flags & PF_MEMALLOC;
-       current->flags |= PF_MEMALLOC;
-       vaddr = kmem_cache_alloc(cachep, GFP_ATOMIC);
-       current->flags &= (~PF_MEMALLOC | flags);
-       return vaddr;
-}
-
-
 static inline void *alloc_pgtable_page(int node)
 {
-       unsigned int flags;
        struct page *page;
        void *vaddr = NULL;
 
-       /* trying to avoid low memory issues */
-       flags = current->flags & PF_MEMALLOC;
-       current->flags |= PF_MEMALLOC;
        page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0);
        if (page)
                vaddr = page_address(page);
-       current->flags &= (~PF_MEMALLOC | flags);
        return vaddr;
 }
 
@@ -424,7 +405,7 @@ static inline void free_pgtable_page(void *vaddr)
 
 static inline void *alloc_domain_mem(void)
 {
-       return iommu_kmem_cache_alloc(iommu_domain_cache);
+       return kmem_cache_alloc(iommu_domain_cache, GFP_ATOMIC);
 }
 
 static void free_domain_mem(void *vaddr)
@@ -434,7 +415,7 @@ static void free_domain_mem(void *vaddr)
 
 static inline void * alloc_devinfo_mem(void)
 {
-       return iommu_kmem_cache_alloc(iommu_devinfo_cache);
+       return kmem_cache_alloc(iommu_devinfo_cache, GFP_ATOMIC);
 }
 
 static inline void free_devinfo_mem(void *vaddr)
@@ -444,7 +425,7 @@ static inline void free_devinfo_mem(void *vaddr)
 
 struct iova *alloc_iova_mem(void)
 {
-       return iommu_kmem_cache_alloc(iommu_iova_cache);
+       return kmem_cache_alloc(iommu_iova_cache, GFP_ATOMIC);
 }
 
 void free_iova_mem(struct iova *iova)
@@ -1530,12 +1511,15 @@ static int domain_context_mapping_one(struct dmar_domain *domain, int segment,
 
                /* Skip top levels of page tables for
                 * iommu which has less agaw than default.
+                * Unnecessary for PT mode.
                 */
-               for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
-                       pgd = phys_to_virt(dma_pte_addr(pgd));
-                       if (!dma_pte_present(pgd)) {
-                               spin_unlock_irqrestore(&iommu->lock, flags);
-                               return -ENOMEM;
+               if (translation != CONTEXT_TT_PASS_THROUGH) {
+                       for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
+                               pgd = phys_to_virt(dma_pte_addr(pgd));
+                               if (!dma_pte_present(pgd)) {
+                                       spin_unlock_irqrestore(&iommu->lock, flags);
+                                       return -ENOMEM;
+                               }
                        }
                }
        }
@@ -1620,7 +1604,7 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
                        return ret;
                parent = parent->bus->self;
        }
-       if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */
+       if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */
                return domain_context_mapping_one(domain,
                                        pci_domain_nr(tmp->subordinate),
                                        tmp->subordinate->number, 0,
@@ -1660,7 +1644,7 @@ static int domain_context_mapped(struct pci_dev *pdev)
                        return ret;
                parent = parent->bus->self;
        }
-       if (tmp->is_pcie)
+       if (pci_is_pcie(tmp))
                return device_context_mapped(iommu, tmp->subordinate->number,
                                             0);
        else
@@ -1830,7 +1814,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
 
        dev_tmp = pci_find_upstream_pcie_bridge(pdev);
        if (dev_tmp) {
-               if (dev_tmp->is_pcie) {
+               if (pci_is_pcie(dev_tmp)) {
                        bus = dev_tmp->subordinate->number;
                        devfn = 0;
                } else {
@@ -2201,7 +2185,7 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
         * the 1:1 domain, just in _case_ one of their siblings turns out
         * not to be able to map all of memory.
         */
-       if (!pdev->is_pcie) {
+       if (!pci_is_pcie(pdev)) {
                if (!pci_is_root_bus(pdev->bus))
                        return 0;
                if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
@@ -3341,7 +3325,7 @@ static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
                                         parent->devfn);
                        parent = parent->bus->self;
                }
-               if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */
+               if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */
                        iommu_detach_dev(iommu,
                                tmp->subordinate->number, 0);
                else /* this is a legacy PCI bridge */
@@ -3642,14 +3626,15 @@ static void intel_iommu_detach_device(struct iommu_domain *domain,
        domain_remove_one_dev_info(dmar_domain, pdev);
 }
 
-static int intel_iommu_map_range(struct iommu_domain *domain,
-                                unsigned long iova, phys_addr_t hpa,
-                                size_t size, int iommu_prot)
+static int intel_iommu_map(struct iommu_domain *domain,
+                          unsigned long iova, phys_addr_t hpa,
+                          int gfp_order, int iommu_prot)
 {
        struct dmar_domain *dmar_domain = domain->priv;
        u64 max_addr;
        int addr_width;
        int prot = 0;
+       size_t size;
        int ret;
 
        if (iommu_prot & IOMMU_READ)
@@ -3659,6 +3644,7 @@ static int intel_iommu_map_range(struct iommu_domain *domain,
        if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
                prot |= DMA_PTE_SNP;
 
+       size     = PAGE_SIZE << gfp_order;
        max_addr = iova + size;
        if (dmar_domain->max_addr < max_addr) {
                int min_agaw;
@@ -3685,19 +3671,19 @@ static int intel_iommu_map_range(struct iommu_domain *domain,
        return ret;
 }
 
-static void intel_iommu_unmap_range(struct iommu_domain *domain,
-                                   unsigned long iova, size_t size)
+static int intel_iommu_unmap(struct iommu_domain *domain,
+                            unsigned long iova, int gfp_order)
 {
        struct dmar_domain *dmar_domain = domain->priv;
-
-       if (!size)
-               return;
+       size_t size = PAGE_SIZE << gfp_order;
 
        dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT,
                            (iova + size - 1) >> VTD_PAGE_SHIFT);
 
        if (dmar_domain->max_addr == iova + size)
                dmar_domain->max_addr = iova;
+
+       return gfp_order;
 }
 
 static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
@@ -3730,8 +3716,8 @@ static struct iommu_ops intel_iommu_ops = {
        .domain_destroy = intel_iommu_domain_destroy,
        .attach_dev     = intel_iommu_attach_device,
        .detach_dev     = intel_iommu_detach_device,
-       .map            = intel_iommu_map_range,
-       .unmap          = intel_iommu_unmap_range,
+       .map            = intel_iommu_map,
+       .unmap          = intel_iommu_unmap,
        .iova_to_phys   = intel_iommu_iova_to_phys,
        .domain_has_cap = intel_iommu_domain_has_cap,
 };