Skip to content

Commit

Permalink
Merge branches 'iommu/fixes', 'x86/amd', 'groups', 'arm/tegra' and 'a…
Browse files Browse the repository at this point in the history
…pi/domain-attr' into next

Conflicts:
	drivers/iommu/iommu.c
	include/linux/iommu.h
  • Loading branch information
Joerg Roedel committed Jul 23, 2012
6 parents 28a33cb + 2c9195e + 2c0ae17 + 7d43c2e + 8ce44a2 + 3177bb7 commit 395e51f
Show file tree
Hide file tree
Showing 32 changed files with 1,839 additions and 506 deletions.
14 changes: 14 additions & 0 deletions Documentation/ABI/testing/sysfs-kernel-iommu_groups
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
What: /sys/kernel/iommu_groups/
Date: May 2012
KernelVersion: v3.5
Contact: Alex Williamson <alex.williamson@redhat.com>
Description: /sys/kernel/iommu_groups/ contains a number of sub-
directories, each representing an IOMMU group. The
name of the sub-directory matches the iommu_group_id()
for the group, which is an integer value. Within each
subdirectory is another directory named "devices" with
links to the sysfs devices contained in this group.
The group directory also optionally contains a "name"
file if the IOMMU driver has chosen to register a more
common name for the group.
Users:
21 changes: 21 additions & 0 deletions Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
NVIDIA Tegra 30 IOMMU H/W, SMMU (System Memory Management Unit)

Required properties:
- compatible : "nvidia,tegra30-smmu"
- reg : Should contain 3 register banks(address and length) for each
of the SMMU register blocks.
- interrupts : Should contain MC General interrupt.
- nvidia,#asids : # of ASIDs
- dma-window : IOVA start address and length.
- nvidia,ahb : phandle to the ahb bus connected to SMMU.

Example:
smmu {
compatible = "nvidia,tegra30-smmu";
reg = <0x7000f010 0x02c
0x7000f1f0 0x010
0x7000f228 0x05c>;
nvidia,#asids = <4>; /* # of ASIDs */
dma-window = <0 0x40000000>; /* IOVA start & length */
nvidia,ahb = <&ahb>;
};
1 change: 0 additions & 1 deletion Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1134,7 +1134,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
forcesac
soft
pt [x86, IA-64]
group_mf [x86, IA-64]


io7= [HW] IO7 for Marvel based alpha systems
Expand Down
2 changes: 0 additions & 2 deletions arch/ia64/include/asm/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ extern void no_iommu_init(void);
extern int force_iommu, no_iommu;
extern int iommu_pass_through;
extern int iommu_detected;
extern int iommu_group_mf;
#else
#define iommu_pass_through (0)
#define no_iommu (1)
#define iommu_detected (0)
#define iommu_group_mf (0)
#endif
extern void iommu_dma_init(void);
extern void machvec_init(const char *name);
Expand Down
1 change: 0 additions & 1 deletion arch/ia64/kernel/pci-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ int force_iommu __read_mostly;
#endif

int iommu_pass_through;
int iommu_group_mf;

/* Dummy device used for NULL arguments (normally ISA). Better would
be probably a smaller DMA mask, but this is bug-to-bug compatible
Expand Down
1 change: 0 additions & 1 deletion arch/x86/include/asm/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ extern struct dma_map_ops nommu_dma_ops;
extern int force_iommu, no_iommu;
extern int iommu_detected;
extern int iommu_pass_through;
extern int iommu_group_mf;

/* 10 seconds */
#define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000)
Expand Down
11 changes: 0 additions & 11 deletions arch/x86/kernel/pci-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,6 @@ int iommu_detected __read_mostly = 0;
*/
int iommu_pass_through __read_mostly;

/*
* Group multi-function PCI devices into a single device-group for the
* iommu_device_group interface. This tells the iommu driver to pretend
* it cannot distinguish between functions of a device, exposing only one
* group for the device. Useful for disallowing use of individual PCI
* functions from userspace drivers.
*/
int iommu_group_mf __read_mostly;

extern struct iommu_table_entry __iommu_table[], __iommu_table_end[];

/* Dummy device used for NULL arguments (normally ISA). */
Expand Down Expand Up @@ -194,8 +185,6 @@ static __init int iommu_setup(char *p)
#endif
if (!strncmp(p, "pt", 2))
iommu_pass_through = 1;
if (!strncmp(p, "group_mf", 8))
iommu_group_mf = 1;

gart_parse_options(p);

Expand Down
6 changes: 5 additions & 1 deletion drivers/iommu/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ menuconfig IOMMU_SUPPORT

if IOMMU_SUPPORT

config OF_IOMMU
def_bool y
depends on OF

# MSM IOMMU support
config MSM_IOMMU
bool "MSM IOMMU Support"
Expand Down Expand Up @@ -154,7 +158,7 @@ config TEGRA_IOMMU_GART

config TEGRA_IOMMU_SMMU
bool "Tegra SMMU IOMMU Support"
depends on ARCH_TEGRA_3x_SOC
depends on ARCH_TEGRA_3x_SOC && TEGRA_AHB
select IOMMU_API
help
Enables support for remapping discontiguous physical memory
Expand Down
1 change: 1 addition & 0 deletions drivers/iommu/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
obj-$(CONFIG_IOMMU_API) += iommu.o
obj-$(CONFIG_OF_IOMMU) += of_iommu.o
obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
Expand Down
99 changes: 71 additions & 28 deletions drivers/iommu/amd_iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,11 +256,21 @@ static bool check_device(struct device *dev)
return true;
}

static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to)
{
pci_dev_put(*from);
*from = to;
}

#define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)

static int iommu_init_device(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct pci_dev *dma_pdev, *pdev = to_pci_dev(dev);
struct iommu_dev_data *dev_data;
struct iommu_group *group;
u16 alias;
int ret;

if (dev->archdata.iommu)
return 0;
Expand All @@ -281,8 +291,43 @@ static int iommu_init_device(struct device *dev)
return -ENOTSUPP;
}
dev_data->alias_data = alias_data;

dma_pdev = pci_get_bus_and_slot(alias >> 8, alias & 0xff);
} else
dma_pdev = pci_dev_get(pdev);

swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev));

if (dma_pdev->multifunction &&
!pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS))
swap_pci_ref(&dma_pdev,
pci_get_slot(dma_pdev->bus,
PCI_DEVFN(PCI_SLOT(dma_pdev->devfn),
0)));

while (!pci_is_root_bus(dma_pdev->bus)) {
if (pci_acs_path_enabled(dma_pdev->bus->self,
NULL, REQ_ACS_FLAGS))
break;

swap_pci_ref(&dma_pdev, pci_dev_get(dma_pdev->bus->self));
}

group = iommu_group_get(&dma_pdev->dev);
pci_dev_put(dma_pdev);
if (!group) {
group = iommu_group_alloc();
if (IS_ERR(group))
return PTR_ERR(group);
}

ret = iommu_group_add_device(group, dev);

iommu_group_put(group);

if (ret)
return ret;

if (pci_iommuv2_capable(pdev)) {
struct amd_iommu *iommu;

Expand Down Expand Up @@ -311,6 +356,8 @@ static void iommu_ignore_device(struct device *dev)

static void iommu_uninit_device(struct device *dev)
{
iommu_group_remove_device(dev);

/*
* Nothing to do here - we keep dev_data around for unplugged devices
* and reuse it when the device is re-plugged - not doing so would
Expand Down Expand Up @@ -384,7 +431,6 @@ DECLARE_STATS_COUNTER(invalidate_iotlb);
DECLARE_STATS_COUNTER(invalidate_iotlb_all);
DECLARE_STATS_COUNTER(pri_requests);


static struct dentry *stats_dir;
static struct dentry *de_fflush;

Expand Down Expand Up @@ -2073,7 +2119,7 @@ static int pdev_iommuv2_enable(struct pci_dev *pdev)
/* FIXME: Move this to PCI code */
#define PCI_PRI_TLP_OFF (1 << 15)

bool pci_pri_tlp_required(struct pci_dev *pdev)
static bool pci_pri_tlp_required(struct pci_dev *pdev)
{
u16 status;
int pos;
Expand Down Expand Up @@ -2254,6 +2300,18 @@ static int device_change_notifier(struct notifier_block *nb,

iommu_init_device(dev);

/*
* dev_data is still NULL and
* got initialized in iommu_init_device
*/
dev_data = get_dev_data(dev);

if (iommu_pass_through || dev_data->iommu_v2) {
dev_data->passthrough = true;
attach_device(dev, pt_domain);
break;
}

domain = domain_for_device(dev);

/* allocate a protection domain if a device is added */
Expand All @@ -2271,10 +2329,7 @@ static int device_change_notifier(struct notifier_block *nb,

dev_data = get_dev_data(dev);

if (!dev_data->passthrough)
dev->archdata.dma_ops = &amd_iommu_dma_ops;
else
dev->archdata.dma_ops = &nommu_dma_ops;
dev->archdata.dma_ops = &amd_iommu_dma_ops;

break;
case BUS_NOTIFY_DEL_DEVICE:
Expand Down Expand Up @@ -2972,6 +3027,11 @@ int __init amd_iommu_init_dma_ops(void)

amd_iommu_stats_init();

if (amd_iommu_unmap_flush)
pr_info("AMD-Vi: IO/TLB flush on unmap enabled\n");
else
pr_info("AMD-Vi: Lazy IO/TLB flushing enabled\n");

return 0;

free_domains:
Expand Down Expand Up @@ -3078,6 +3138,10 @@ static int amd_iommu_domain_init(struct iommu_domain *dom)

dom->priv = domain;

dom->geometry.aperture_start = 0;
dom->geometry.aperture_end = ~0ULL;
dom->geometry.force_aperture = true;

return 0;

out_free:
Expand Down Expand Up @@ -3236,26 +3300,6 @@ static int amd_iommu_domain_has_cap(struct iommu_domain *domain,
return 0;
}

static int amd_iommu_device_group(struct device *dev, unsigned int *groupid)
{
struct iommu_dev_data *dev_data = dev->archdata.iommu;
struct pci_dev *pdev = to_pci_dev(dev);
u16 devid;

if (!dev_data)
return -ENODEV;

if (pdev->is_virtfn || !iommu_group_mf)
devid = dev_data->devid;
else
devid = calc_devid(pdev->bus->number,
PCI_DEVFN(PCI_SLOT(pdev->devfn), 0));

*groupid = amd_iommu_alias_table[devid];

return 0;
}

static struct iommu_ops amd_iommu_ops = {
.domain_init = amd_iommu_domain_init,
.domain_destroy = amd_iommu_domain_destroy,
Expand All @@ -3265,7 +3309,6 @@ static struct iommu_ops amd_iommu_ops = {
.unmap = amd_iommu_unmap,
.iova_to_phys = amd_iommu_iova_to_phys,
.domain_has_cap = amd_iommu_domain_has_cap,
.device_group = amd_iommu_device_group,
.pgsize_bitmap = AMD_IOMMU_PGSIZES,
};

Expand Down
Loading

0 comments on commit 395e51f

Please sign in to comment.