mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/linux-2.6-iommu
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/linux-2.6-iommu: (89 commits) AMD IOMMU: remove now unnecessary #ifdefs AMD IOMMU: prealloc_protection_domains should be static kvm/iommu: fix compile warning AMD IOMMU: add statistics about total number of map requests AMD IOMMU: add statistics about allocated io memory AMD IOMMU: add stats counter for domain tlb flushes AMD IOMMU: add stats counter for single iommu domain tlb flushes AMD IOMMU: add stats counter for cross-page request AMD IOMMU: add stats counter for free_coherent requests AMD IOMMU: add stats counter for alloc_coherent requests AMD IOMMU: add stats counter for unmap_sg requests AMD IOMMU: add stats counter for map_sg requests AMD IOMMU: add stats counter for unmap_single requests AMD IOMMU: add stats counter for map_single requests AMD IOMMU: add stats counter for completion wait events AMD IOMMU: add init code for statistic collection AMD IOMMU: add necessary header defines for stats counting AMD IOMMU: add Kconfig entry for statistic collection code AMD IOMMU: use dev_name in iommu_enable function AMD IOMMU: use calc_devid in prealloc_protection_domains ...
This commit is contained in:
commit
269b012321
22 changed files with 1893 additions and 463 deletions
|
|
@ -11,6 +11,7 @@ obj-$(CONFIG_FW_LOADER) += firmware_class.o
|
|||
obj-$(CONFIG_NUMA) += node.o
|
||||
obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
|
||||
obj-$(CONFIG_SMP) += topology.o
|
||||
obj-$(CONFIG_IOMMU_API) += iommu.o
|
||||
ifeq ($(CONFIG_SYSFS),y)
|
||||
obj-$(CONFIG_MODULES) += module.o
|
||||
endif
|
||||
|
|
|
|||
100
drivers/base/iommu.c
Normal file
100
drivers/base/iommu.c
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
|
||||
* Author: Joerg Roedel <joerg.roedel@amd.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/iommu.h>
|
||||
|
||||
static struct iommu_ops *iommu_ops;
|
||||
|
||||
void register_iommu(struct iommu_ops *ops)
|
||||
{
|
||||
if (iommu_ops)
|
||||
BUG();
|
||||
|
||||
iommu_ops = ops;
|
||||
}
|
||||
|
||||
bool iommu_found()
|
||||
{
|
||||
return iommu_ops != NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iommu_found);
|
||||
|
||||
struct iommu_domain *iommu_domain_alloc(void)
|
||||
{
|
||||
struct iommu_domain *domain;
|
||||
int ret;
|
||||
|
||||
domain = kmalloc(sizeof(*domain), GFP_KERNEL);
|
||||
if (!domain)
|
||||
return NULL;
|
||||
|
||||
ret = iommu_ops->domain_init(domain);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
|
||||
return domain;
|
||||
|
||||
out_free:
|
||||
kfree(domain);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iommu_domain_alloc);
|
||||
|
||||
void iommu_domain_free(struct iommu_domain *domain)
|
||||
{
|
||||
iommu_ops->domain_destroy(domain);
|
||||
kfree(domain);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iommu_domain_free);
|
||||
|
||||
int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
|
||||
{
|
||||
return iommu_ops->attach_dev(domain, dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iommu_attach_device);
|
||||
|
||||
void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
|
||||
{
|
||||
iommu_ops->detach_dev(domain, dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iommu_detach_device);
|
||||
|
||||
int iommu_map_range(struct iommu_domain *domain, unsigned long iova,
|
||||
phys_addr_t paddr, size_t size, int prot)
|
||||
{
|
||||
return iommu_ops->map(domain, iova, paddr, size, prot);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iommu_map_range);
|
||||
|
||||
void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova,
|
||||
size_t size)
|
||||
{
|
||||
iommu_ops->unmap(domain, iova, size);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iommu_unmap_range);
|
||||
|
||||
phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
|
||||
unsigned long iova)
|
||||
{
|
||||
return iommu_ops->iova_to_phys(domain, iova);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iommu_iova_to_phys);
|
||||
|
|
@ -191,26 +191,17 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
|
|||
static int __init dmar_parse_dev(struct dmar_drhd_unit *dmaru)
|
||||
{
|
||||
struct acpi_dmar_hardware_unit *drhd;
|
||||
static int include_all;
|
||||
int ret = 0;
|
||||
|
||||
drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
|
||||
|
||||
if (!dmaru->include_all)
|
||||
ret = dmar_parse_dev_scope((void *)(drhd + 1),
|
||||
if (dmaru->include_all)
|
||||
return 0;
|
||||
|
||||
ret = dmar_parse_dev_scope((void *)(drhd + 1),
|
||||
((void *)drhd) + drhd->header.length,
|
||||
&dmaru->devices_cnt, &dmaru->devices,
|
||||
drhd->segment);
|
||||
else {
|
||||
/* Only allow one INCLUDE_ALL */
|
||||
if (include_all) {
|
||||
printk(KERN_WARNING PREFIX "Only one INCLUDE_ALL "
|
||||
"device scope is allowed\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
include_all = 1;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
list_del(&dmaru->list);
|
||||
kfree(dmaru);
|
||||
|
|
@ -384,12 +375,21 @@ int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
|
|||
struct dmar_drhd_unit *
|
||||
dmar_find_matched_drhd_unit(struct pci_dev *dev)
|
||||
{
|
||||
struct dmar_drhd_unit *drhd = NULL;
|
||||
struct dmar_drhd_unit *dmaru = NULL;
|
||||
struct acpi_dmar_hardware_unit *drhd;
|
||||
|
||||
list_for_each_entry(drhd, &dmar_drhd_units, list) {
|
||||
if (drhd->include_all || dmar_pci_device_match(drhd->devices,
|
||||
drhd->devices_cnt, dev))
|
||||
return drhd;
|
||||
list_for_each_entry(dmaru, &dmar_drhd_units, list) {
|
||||
drhd = container_of(dmaru->hdr,
|
||||
struct acpi_dmar_hardware_unit,
|
||||
header);
|
||||
|
||||
if (dmaru->include_all &&
|
||||
drhd->segment == pci_domain_nr(dev->bus))
|
||||
return dmaru;
|
||||
|
||||
if (dmar_pci_device_match(dmaru->devices,
|
||||
dmaru->devices_cnt, dev))
|
||||
return dmaru;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
@ -491,6 +491,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
|
|||
int map_size;
|
||||
u32 ver;
|
||||
static int iommu_allocated = 0;
|
||||
int agaw;
|
||||
|
||||
iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
|
||||
if (!iommu)
|
||||
|
|
@ -506,6 +507,15 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
|
|||
iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
|
||||
iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
|
||||
|
||||
agaw = iommu_calculate_agaw(iommu);
|
||||
if (agaw < 0) {
|
||||
printk(KERN_ERR
|
||||
"Cannot get a valid agaw for iommu (seq_id = %d)\n",
|
||||
iommu->seq_id);
|
||||
goto error;
|
||||
}
|
||||
iommu->agaw = agaw;
|
||||
|
||||
/* the registers might be more than one page */
|
||||
map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
|
||||
cap_max_fault_reg_offset(iommu->cap));
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue