1789 lines
62 KiB
Diff
1789 lines
62 KiB
Diff
From 35412fc5240640825faa81068e5269069f90d86f Mon Sep 17 00:00:00 2001
|
|
From: Jayachandran C <jnair@caviumnetworks.com>
|
|
Date: Thu, 13 Apr 2017 20:30:44 +0000
|
|
Subject: [PATCH 01/41] PCI: Add device flag PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT
|
|
|
|
Add a new quirk flag PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT to limit the DMA alias
|
|
search to go no further than the bridge where the IOMMU unit is attached.
|
|
|
|
The flag will be used to indicate a bridge device which forwards the
|
|
address translation requests to the IOMMU, i.e., where the interrupt and
|
|
DMA requests leave the PCIe hierarchy and go into the system blocks.
|
|
|
|
Usually this happens at the PCI RC, so this flag is not needed. But on
|
|
systems where there are bridges that introduce aliases above the IOMMU,
|
|
this flag prevents pci_for_each_dma_alias() from generating aliases that
|
|
the IOMMU will never see.
|
|
|
|
The function pci_for_each_dma_alias() is updated to stop when it see a
|
|
bridge with this flag set.
|
|
|
|
Link: https://bugzilla.kernel.org/show_bug.cgi?id=195447
|
|
Signed-off-by: Jayachandran C <jnair@caviumnetworks.com>
|
|
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
|
|
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
|
|
Acked-by: David Daney <david.daney@cavium.com>
|
|
(cherry picked from commit ffff885832101543c002cef7abcab0fd27a9aee1)
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/pci/search.c | 4 ++++
|
|
include/linux/pci.h | 2 ++
|
|
2 files changed, 6 insertions(+)
|
|
|
|
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
|
|
index 33e0f033a48e..4c6044ad7368 100644
|
|
--- a/drivers/pci/search.c
|
|
+++ b/drivers/pci/search.c
|
|
@@ -60,6 +60,10 @@ int pci_for_each_dma_alias(struct pci_dev *pdev,
|
|
|
|
tmp = bus->self;
|
|
|
|
+ /* stop at bridge where translation unit is associated */
|
|
+ if (tmp->dev_flags & PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT)
|
|
+ return ret;
|
|
+
|
|
/*
|
|
* PCIe-to-PCI/X bridges alias transactions from downstream
|
|
* devices using the subordinate bus number (PCI Express to
|
|
diff --git a/include/linux/pci.h b/include/linux/pci.h
|
|
index eb3da1a04e6c..3f596acc05be 100644
|
|
--- a/include/linux/pci.h
|
|
+++ b/include/linux/pci.h
|
|
@@ -178,6 +178,8 @@ enum pci_dev_flags {
|
|
PCI_DEV_FLAGS_NO_PM_RESET = (__force pci_dev_flags_t) (1 << 7),
|
|
/* Get VPD from function 0 VPD */
|
|
PCI_DEV_FLAGS_VPD_REF_F0 = (__force pci_dev_flags_t) (1 << 8),
|
|
+ /* a non-root bridge where translation occurs, stop alias search here */
|
|
+ PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT = (__force pci_dev_flags_t) (1 << 9),
|
|
/*
|
|
* Resume before calling the driver's system suspend hooks, disabling
|
|
* the direct_complete optimization.
|
|
--
|
|
2.11.0
|
|
|
|
From 2fe0ffd43a57035207a124421e9164401aabb9d4 Mon Sep 17 00:00:00 2001
|
|
From: Jayachandran C <jnair@caviumnetworks.com>
|
|
Date: Thu, 13 Apr 2017 20:30:45 +0000
|
|
Subject: [PATCH 02/41] PCI: Avoid generating invalid ThunderX2 DMA aliases
|
|
|
|
On Cavium ThunderX2 arm64 SoCs (formerly known as Broadcom Vulcan), the PCI
|
|
topology is slightly unusual. For a multi-node system, it looks like:
|
|
|
|
00:00.0 PCI bridge to [bus 01-1e]
|
|
01:0a.0 PCI-to-PCIe bridge to [bus 02-04]
|
|
02:00.0 PCIe Root Port bridge to [bus 03-04] (XLATE_ROOT)
|
|
03:00.0 PCIe Endpoint
|
|
|
|
pci_for_each_dma_alias() assumes IOMMU translation is done at the root of
|
|
the PCI hierarchy. It generates 03:00.0, 01:0a.0, and 00:00.0 as DMA
|
|
aliases for 03:00.0 because buses 01 and 00 are non-PCIe buses that don't
|
|
carry the Requester ID.
|
|
|
|
Because the ThunderX2 IOMMU is at 02:00.0, the Requester IDs 01:0a.0 and
|
|
00:00.0 are never valid for the endpoint. This quirk stops alias
|
|
generation at the XLATE_ROOT bridge so we won't generate 01:0a.0 or
|
|
00:00.0.
|
|
|
|
The current IOMMU code only maps the last alias (this is a separate bug in
|
|
itself). Prior to this quirk, we only created IOMMU mappings for the
|
|
invalid Requester ID 00:00:0, which never matched any DMA transactions.
|
|
|
|
With this quirk, we create IOMMU mappings for a valid Requester ID, which
|
|
fixes devices with no aliases but leaves devices with aliases still broken.
|
|
|
|
The last alias for the endpoint is also used by the ARM GICv3 MSI-X code.
|
|
Without this quirk, the GIC Interrupt Translation Tables are setup with the
|
|
invalid Requester ID, and the MSI-X generated by the device fails to be
|
|
translated and routed.
|
|
|
|
Link: https://bugzilla.kernel.org/show_bug.cgi?id=195447
|
|
Signed-off-by: Jayachandran C <jnair@caviumnetworks.com>
|
|
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
|
|
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
|
|
Acked-by: David Daney <david.daney@cavium.com>
|
|
(cherry picked from commit 45a2329367386342d41ea9414c88b023f5a79055)
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/pci/quirks.c | 14 ++++++++++++++
|
|
1 file changed, 14 insertions(+)
|
|
|
|
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
|
|
index 673683660b5c..96d332978719 100644
|
|
--- a/drivers/pci/quirks.c
|
|
+++ b/drivers/pci/quirks.c
|
|
@@ -3958,6 +3958,20 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2260, quirk_mic_x200_dma_alias);
|
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2264, quirk_mic_x200_dma_alias);
|
|
|
|
/*
|
|
+ * The IOMMU and interrupt controller on Broadcom Vulcan/Cavium ThunderX2 are
|
|
+ * associated not at the root bus, but at a bridge below. This quirk avoids
|
|
+ * generating invalid DMA aliases.
|
|
+ */
|
|
+static void quirk_bridge_cavm_thrx2_pcie_root(struct pci_dev *pdev)
|
|
+{
|
|
+ pdev->dev_flags |= PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT;
|
|
+}
|
|
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, 0x9000,
|
|
+ quirk_bridge_cavm_thrx2_pcie_root);
|
|
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, 0x9084,
|
|
+ quirk_bridge_cavm_thrx2_pcie_root);
|
|
+
|
|
+/*
|
|
* Intersil/Techwell TW686[4589]-based video capture cards have an empty (zero)
|
|
* class code. Fix it.
|
|
*/
|
|
--
|
|
2.11.0
|
|
|
|
From 153c6a5945340315126a7ec31cf52129ad782398 Mon Sep 17 00:00:00 2001
|
|
From: Ashok Kumar Sekar <asekar@redhat.com>
|
|
Date: Fri, 23 Sep 2016 04:16:19 -0700
|
|
Subject: [PATCH 03/41] PCI: Vulcan: AHCI PCI bar fix for Broadcom Vulcan early
|
|
silicon
|
|
|
|
PCI BAR 5 is not setup correctly for the on-board AHCI
|
|
controller on Broadcom's Vulcan processor. Added a quirk to fix BAR 5
|
|
by using BAR 4's resources which are populated correctly but NOT used
|
|
by the AHCI controller actually.
|
|
|
|
Signed-off-by: Ashok Kumar Sekar <asekar@redhat.com>
|
|
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/pci/quirks.c | 24 ++++++++++++++++++++++++
|
|
1 file changed, 24 insertions(+)
|
|
|
|
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
|
|
index 96d332978719..0966a22eae13 100644
|
|
--- a/drivers/pci/quirks.c
|
|
+++ b/drivers/pci/quirks.c
|
|
@@ -3972,6 +3972,30 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, 0x9084,
|
|
quirk_bridge_cavm_thrx2_pcie_root);
|
|
|
|
/*
|
|
+ * PCI BAR 5 is not setup correctly for the on-board AHCI controller
|
|
+ * on Broadcom's Vulcan processor. Added a quirk to fix BAR 5 by
|
|
+ * using BAR 4's resources which are populated correctly and NOT
|
|
+ * actually used by the AHCI controller.
|
|
+ */
|
|
+static void quirk_fix_vulcan_ahci_bars(struct pci_dev *dev)
|
|
+{
|
|
+ struct resource *r = &dev->resource[4];
|
|
+
|
|
+ if (!(r->flags & IORESOURCE_MEM) || (r->start == 0))
|
|
+ return;
|
|
+
|
|
+ /* Set BAR5 resource to BAR4 */
|
|
+ dev->resource[5] = *r;
|
|
+
|
|
+ /* Update BAR5 in pci config space */
|
|
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_5, r->start);
|
|
+
|
|
+ /* Clear BAR4's resource */
|
|
+ memset(r, 0, sizeof(*r));
|
|
+}
|
|
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, 0x9027, quirk_fix_vulcan_ahci_bars);
|
|
+
|
|
+/*
|
|
* Intersil/Techwell TW686[4589]-based video capture cards have an empty (zero)
|
|
* class code. Fix it.
|
|
*/
|
|
--
|
|
2.11.0
|
|
|
|
From bfe8e2f6bb2922b76650e3d43782132b0c388508 Mon Sep 17 00:00:00 2001
|
|
From: Jayachandran C <jnair@caviumnetworks.com>
|
|
Date: Fri, 10 Mar 2017 10:04:52 +0000
|
|
Subject: [PATCH 04/41] ahci: thunderx2: Fix for errata that affects stop
|
|
engine
|
|
|
|
Apply workaround for this errata:
|
|
Synopsis: Resetting PxCMD.ST may hang the SATA device
|
|
|
|
Description: An internal ping-pong buffer state is not reset
|
|
correctly for an PxCMD.ST=0 command for a SATA channel. This
|
|
may cause the SATA interface to hang when a PxCMD.ST=0 command
|
|
is received.
|
|
|
|
Workaround: A SATA_BIU_CORE_ENABLE.sw_init_bsi must be asserted
|
|
by the driver whenever the PxCMD.ST needs to be de-asserted. This
|
|
will reset both the ports. So, it may not always work in a 2
|
|
channel SATA system.
|
|
|
|
Resolution: Fix in B0.
|
|
|
|
Add the code to ahci_stop_engine() to do this. It is not easy to
|
|
stop the other "port" since it is associated with a different AHCI
|
|
interface. Please note that with this fix, SATA reset does not
|
|
hang any more, but it can cause failures on the other interface
|
|
if that is in active use.
|
|
|
|
Unfortunately, we have nothing other the the CPU ID to check if the
|
|
SATA block has this issue.
|
|
|
|
Signed-off-by: Jayachandran C <jnair@caviumnetworks.com>
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/ata/libahci.c | 14 ++++++++++++++
|
|
1 file changed, 14 insertions(+)
|
|
|
|
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
|
|
index 3159f9e66d8f..5f64275ef387 100644
|
|
--- a/drivers/ata/libahci.c
|
|
+++ b/drivers/ata/libahci.c
|
|
@@ -664,6 +664,20 @@ int ahci_stop_engine(struct ata_port *ap)
|
|
tmp &= ~PORT_CMD_START;
|
|
writel(tmp, port_mmio + PORT_CMD);
|
|
|
|
+#ifdef CONFIG_ARM64
|
|
+ /* Rev Ax of Cavium CN99XX needs a hack for port stop */
|
|
+ if (MIDR_IS_CPU_MODEL_RANGE(read_cpuid_id(),
|
|
+ MIDR_CPU_MODEL(ARM_CPU_IMP_BRCM, BRCM_CPU_PART_VULCAN),
|
|
+ MIDR_CPU_VAR_REV(0, 0),
|
|
+ MIDR_CPU_VAR_REV(0, MIDR_REVISION_MASK))) {
|
|
+ tmp = readl(hpriv->mmio + 0x8000);
|
|
+ writel(tmp | (1 << 26), hpriv->mmio + 0x8000);
|
|
+ udelay(1);
|
|
+ writel(tmp & ~(1 << 26), hpriv->mmio + 0x8000);
|
|
+ dev_warn(ap->host->dev, "CN99XX stop engine fix applied!\n");
|
|
+ }
|
|
+#endif
|
|
+
|
|
/* wait for engine to stop. This could be as long as 500 msec */
|
|
tmp = ata_wait_register(ap, port_mmio + PORT_CMD,
|
|
PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
|
|
--
|
|
2.11.0
|
|
|
|
From 4bd9ffa0dc3a064f1191b117cd3b43e2fa310c81 Mon Sep 17 00:00:00 2001
|
|
From: Sunil Goutham <sgoutham@cavium.com>
|
|
Date: Tue, 28 Mar 2017 16:11:12 +0530
|
|
Subject: [PATCH 14/41] iommu/arm-smmu: Fix 16-bit ASID configuration
|
|
|
|
16-bit ASID should be enabled before initializing TTBR0/1,
|
|
otherwise only LSB 8-bit ASID will be considered. Hence
|
|
moving configuration of TTBCR register ahead of TTBR0/1
|
|
while initializing context bank.
|
|
|
|
Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
|
|
[will: rewrote comment]
|
|
Signed-off-by: Will Deacon <will.deacon@arm.com>
|
|
|
|
(cherry picked from commit 125458ab3aefe9cf2f72dcfe7338dc9ad967da0b)
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/iommu/arm-smmu.c | 42 +++++++++++++++++++++++-------------------
|
|
1 file changed, 23 insertions(+), 19 deletions(-)
|
|
|
|
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
|
|
index b493c99e17f7..9905f08058b6 100644
|
|
--- a/drivers/iommu/arm-smmu.c
|
|
+++ b/drivers/iommu/arm-smmu.c
|
|
@@ -758,6 +758,29 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
|
|
}
|
|
writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(cfg->cbndx));
|
|
|
|
+ /*
|
|
+ * TTBCR
|
|
+ * We must write this before the TTBRs, since it determines the
|
|
+ * access behaviour of some fields (in particular, ASID[15:8]).
|
|
+ */
|
|
+ if (stage1) {
|
|
+ if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH32_S) {
|
|
+ reg = pgtbl_cfg->arm_v7s_cfg.tcr;
|
|
+ reg2 = 0;
|
|
+ } else {
|
|
+ reg = pgtbl_cfg->arm_lpae_s1_cfg.tcr;
|
|
+ reg2 = pgtbl_cfg->arm_lpae_s1_cfg.tcr >> 32;
|
|
+ reg2 |= TTBCR2_SEP_UPSTREAM;
|
|
+ if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64)
|
|
+ reg2 |= TTBCR2_AS;
|
|
+ }
|
|
+ if (smmu->version > ARM_SMMU_V1)
|
|
+ writel_relaxed(reg2, cb_base + ARM_SMMU_CB_TTBCR2);
|
|
+ } else {
|
|
+ reg = pgtbl_cfg->arm_lpae_s2_cfg.vtcr;
|
|
+ }
|
|
+ writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR);
|
|
+
|
|
/* TTBRs */
|
|
if (stage1) {
|
|
u16 asid = ARM_SMMU_CB_ASID(smmu, cfg);
|
|
@@ -781,25 +804,6 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
|
|
writeq_relaxed(reg64, cb_base + ARM_SMMU_CB_TTBR0);
|
|
}
|
|
|
|
- /* TTBCR */
|
|
- if (stage1) {
|
|
- if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH32_S) {
|
|
- reg = pgtbl_cfg->arm_v7s_cfg.tcr;
|
|
- reg2 = 0;
|
|
- } else {
|
|
- reg = pgtbl_cfg->arm_lpae_s1_cfg.tcr;
|
|
- reg2 = pgtbl_cfg->arm_lpae_s1_cfg.tcr >> 32;
|
|
- reg2 |= TTBCR2_SEP_UPSTREAM;
|
|
- if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64)
|
|
- reg2 |= TTBCR2_AS;
|
|
- }
|
|
- if (smmu->version > ARM_SMMU_V1)
|
|
- writel_relaxed(reg2, cb_base + ARM_SMMU_CB_TTBCR2);
|
|
- } else {
|
|
- reg = pgtbl_cfg->arm_lpae_s2_cfg.vtcr;
|
|
- }
|
|
- writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR);
|
|
-
|
|
/* MAIRs (stage-1 only) */
|
|
if (stage1) {
|
|
if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH32_S) {
|
|
--
|
|
2.11.0
|
|
|
|
From a2eca90cb82c389bbe1da93a08355210e7c5c393 Mon Sep 17 00:00:00 2001
|
|
From: Robert Richter <rrichter@cavium.com>
|
|
Date: Mon, 13 Mar 2017 11:39:01 +0100
|
|
Subject: [PATCH 15/41] iommu/arm-smmu: Print message when Cavium erratum 27704
|
|
was detected
|
|
|
|
Firmware is responsible for properly enabling smmu workarounds. Print
|
|
a message for better diagnostics when Cavium erratum 27704 was
|
|
detected.
|
|
|
|
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
Signed-off-by: Will Deacon <will.deacon@arm.com>
|
|
(cherry picked from commit 53c35dce45713d2a554109c21a8cd617d09eba50)
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/iommu/arm-smmu.c | 1 +
|
|
1 file changed, 1 insertion(+)
|
|
|
|
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
|
|
index 9905f08058b6..e021b360e315 100644
|
|
--- a/drivers/iommu/arm-smmu.c
|
|
+++ b/drivers/iommu/arm-smmu.c
|
|
@@ -1891,6 +1891,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
|
|
atomic_add_return(smmu->num_context_banks,
|
|
&cavium_smmu_context_count);
|
|
smmu->cavium_id_base -= smmu->num_context_banks;
|
|
+ dev_notice(smmu->dev, "\tenabling workaround for Cavium erratum 27704\n");
|
|
}
|
|
|
|
/* ID2 */
|
|
--
|
|
2.11.0
|
|
|
|
From e319b8d378a4701d36030e140d17fb48aea1ff32 Mon Sep 17 00:00:00 2001
|
|
From: Robert Richter <rrichter@cavium.com>
|
|
Date: Thu, 16 Mar 2017 18:01:59 +0100
|
|
Subject: [PATCH 16/41] iommu/arm-smmu, ACPI: Enable Cavium SMMU-v2
|
|
|
|
In next IORT spec release there will be a definition of a Cavium
|
|
specific model. Until then, enable the Cavium SMMU using cpu id
|
|
registers. All versions of Cavium's SMMUv2 implementation must be
|
|
enabled.
|
|
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/iommu/arm-smmu.c | 22 +++++++++++++++++++++-
|
|
1 file changed, 21 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
|
|
index e021b360e315..24a1df09eaac 100644
|
|
--- a/drivers/iommu/arm-smmu.c
|
|
+++ b/drivers/iommu/arm-smmu.c
|
|
@@ -53,6 +53,8 @@
|
|
|
|
#include <linux/amba/bus.h>
|
|
|
|
+#include <asm/cputype.h>
|
|
+
|
|
#include "io-pgtable.h"
|
|
|
|
/* Maximum number of context banks per SMMU */
|
|
@@ -1986,6 +1988,24 @@ static const struct of_device_id arm_smmu_of_match[] = {
|
|
MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
|
|
|
|
#ifdef CONFIG_ACPI
|
|
+
|
|
+static int acpi_smmu_enable_cavium(struct arm_smmu_device *smmu, int ret)
|
|
+{
|
|
+ u32 cpu_model;
|
|
+
|
|
+ if (!IS_ENABLED(CONFIG_ARM64))
|
|
+ return ret;
|
|
+
|
|
+ cpu_model = read_cpuid_id() & MIDR_CPU_MODEL_MASK;
|
|
+ if (cpu_model != MIDR_THUNDERX)
|
|
+ return ret;
|
|
+
|
|
+ smmu->version = ARM_SMMU_V2;
|
|
+ smmu->model = CAVIUM_SMMUV2;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu)
|
|
{
|
|
int ret = 0;
|
|
@@ -2008,7 +2028,7 @@ static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu)
|
|
ret = -ENODEV;
|
|
}
|
|
|
|
- return ret;
|
|
+ return acpi_smmu_enable_cavium(smmu, ret);
|
|
}
|
|
|
|
static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
|
|
--
|
|
2.11.0
|
|
|
|
From 7d2abb4fa3e9dcebd3081cb91d84bd7339e29431 Mon Sep 17 00:00:00 2001
|
|
From: Will Deacon <will.deacon@arm.com>
|
|
Date: Fri, 6 Jan 2017 16:28:17 +0000
|
|
Subject: [PATCH 21/41] iommu/arm-smmu: Restrict domain attributes to UNMANAGED
|
|
domains
|
|
|
|
The ARM SMMU drivers provide a DOMAIN_ATTR_NESTING domain attribute,
|
|
which allows callers of the IOMMU API to request that the page table
|
|
for a domain is installed at stage-2, if supported by the hardware.
|
|
|
|
Since setting this attribute only makes sense for UNMANAGED domains,
|
|
this patch returns -ENODEV if the domain_{get,set}_attr operations are
|
|
called on other domain types.
|
|
|
|
Signed-off-by: Will Deacon <will.deacon@arm.com>
|
|
(cherry picked from commit 0834cc28fa56c65887c614b6c045be2ba06fdcb0)
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/iommu/arm-smmu-v3.c | 6 ++++++
|
|
drivers/iommu/arm-smmu.c | 6 ++++++
|
|
2 files changed, 12 insertions(+)
|
|
|
|
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
|
|
index 591bb96047c9..b47a88757c18 100644
|
|
--- a/drivers/iommu/arm-smmu-v3.c
|
|
+++ b/drivers/iommu/arm-smmu-v3.c
|
|
@@ -1837,6 +1837,9 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain,
|
|
{
|
|
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
|
|
|
|
+ if (domain->type != IOMMU_DOMAIN_UNMANAGED)
|
|
+ return -EINVAL;
|
|
+
|
|
switch (attr) {
|
|
case DOMAIN_ATTR_NESTING:
|
|
*(int *)data = (smmu_domain->stage == ARM_SMMU_DOMAIN_NESTED);
|
|
@@ -1852,6 +1855,9 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain,
|
|
int ret = 0;
|
|
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
|
|
|
|
+ if (domain->type != IOMMU_DOMAIN_UNMANAGED)
|
|
+ return -EINVAL;
|
|
+
|
|
mutex_lock(&smmu_domain->init_mutex);
|
|
|
|
switch (attr) {
|
|
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
|
|
index 24a1df09eaac..cdedb0933d48 100644
|
|
--- a/drivers/iommu/arm-smmu.c
|
|
+++ b/drivers/iommu/arm-smmu.c
|
|
@@ -1555,6 +1555,9 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain,
|
|
{
|
|
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
|
|
|
|
+ if (domain->type != IOMMU_DOMAIN_UNMANAGED)
|
|
+ return -EINVAL;
|
|
+
|
|
switch (attr) {
|
|
case DOMAIN_ATTR_NESTING:
|
|
*(int *)data = (smmu_domain->stage == ARM_SMMU_DOMAIN_NESTED);
|
|
@@ -1570,6 +1573,9 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain,
|
|
int ret = 0;
|
|
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
|
|
|
|
+ if (domain->type != IOMMU_DOMAIN_UNMANAGED)
|
|
+ return -EINVAL;
|
|
+
|
|
mutex_lock(&smmu_domain->init_mutex);
|
|
|
|
switch (attr) {
|
|
--
|
|
2.11.0
|
|
|
|
From 2142445d92c24592e57646087340dbd425fdfb6b Mon Sep 17 00:00:00 2001
|
|
From: Will Deacon <will.deacon@arm.com>
|
|
Date: Fri, 6 Jan 2017 16:56:03 +0000
|
|
Subject: [PATCH 22/41] iommu/arm-smmu: Install bypass S2CRs for
|
|
IOMMU_DOMAIN_IDENTITY domains
|
|
|
|
In preparation for allowing the default domain type to be overridden,
|
|
this patch adds support for IOMMU_DOMAIN_IDENTITY domains to the
|
|
ARM SMMU driver.
|
|
|
|
An identity domain is created by placing the corresponding S2CR
|
|
registers into "bypass" mode, which allows transactions to flow through
|
|
the SMMU without any translation.
|
|
|
|
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
|
|
Signed-off-by: Will Deacon <will.deacon@arm.com>
|
|
(cherry picked from commit 61bc671179f19060be883068b6d3d82ae0b24bc0)
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/iommu/arm-smmu.c | 20 +++++++++++++++++---
|
|
1 file changed, 17 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
|
|
index cdedb0933d48..88e9131b6900 100644
|
|
--- a/drivers/iommu/arm-smmu.c
|
|
+++ b/drivers/iommu/arm-smmu.c
|
|
@@ -418,6 +418,7 @@ enum arm_smmu_domain_stage {
|
|
ARM_SMMU_DOMAIN_S1 = 0,
|
|
ARM_SMMU_DOMAIN_S2,
|
|
ARM_SMMU_DOMAIN_NESTED,
|
|
+ ARM_SMMU_DOMAIN_BYPASS,
|
|
};
|
|
|
|
struct arm_smmu_domain {
|
|
@@ -844,6 +845,12 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
|
|
if (smmu_domain->smmu)
|
|
goto out_unlock;
|
|
|
|
+ if (domain->type == IOMMU_DOMAIN_IDENTITY) {
|
|
+ smmu_domain->stage = ARM_SMMU_DOMAIN_BYPASS;
|
|
+ smmu_domain->smmu = smmu;
|
|
+ goto out_unlock;
|
|
+ }
|
|
+
|
|
/*
|
|
* Mapping the requested stage onto what we support is surprisingly
|
|
* complicated, mainly because the spec allows S1+S2 SMMUs without
|
|
@@ -1004,7 +1011,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
|
|
void __iomem *cb_base;
|
|
int irq;
|
|
|
|
- if (!smmu)
|
|
+ if (!smmu || domain->type == IOMMU_DOMAIN_IDENTITY)
|
|
return;
|
|
|
|
/*
|
|
@@ -1027,7 +1034,9 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
|
|
{
|
|
struct arm_smmu_domain *smmu_domain;
|
|
|
|
- if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
|
|
+ if (type != IOMMU_DOMAIN_UNMANAGED &&
|
|
+ type != IOMMU_DOMAIN_DMA &&
|
|
+ type != IOMMU_DOMAIN_IDENTITY)
|
|
return NULL;
|
|
/*
|
|
* Allocate the domain and initialise some of its data structures.
|
|
@@ -1256,10 +1265,15 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
|
|
{
|
|
struct arm_smmu_device *smmu = smmu_domain->smmu;
|
|
struct arm_smmu_s2cr *s2cr = smmu->s2crs;
|
|
- enum arm_smmu_s2cr_type type = S2CR_TYPE_TRANS;
|
|
u8 cbndx = smmu_domain->cfg.cbndx;
|
|
+ enum arm_smmu_s2cr_type type;
|
|
int i, idx;
|
|
|
|
+ if (smmu_domain->stage == ARM_SMMU_DOMAIN_BYPASS)
|
|
+ type = S2CR_TYPE_BYPASS;
|
|
+ else
|
|
+ type = S2CR_TYPE_TRANS;
|
|
+
|
|
for_each_cfg_sme(fwspec, i, idx) {
|
|
if (type == s2cr[idx].type && cbndx == s2cr[idx].cbndx)
|
|
continue;
|
|
--
|
|
2.11.0
|
|
|
|
From 5f43f8eb48ae0c6c6c74b4a299e5ba1d6d1fe0b3 Mon Sep 17 00:00:00 2001
|
|
From: Will Deacon <will.deacon@arm.com>
|
|
Date: Wed, 1 Mar 2017 21:11:29 +0000
|
|
Subject: [PATCH 23/41] iommu/arm-smmu-v3: Make arm_smmu_install_ste_for_dev
|
|
return void
|
|
|
|
arm_smmu_install_ste_for_dev cannot fail and always returns 0, however
|
|
the fact that it returns int means that callers end up implementing
|
|
redundant error handling code which complicates STE tracking and is
|
|
never executed.
|
|
|
|
This patch changes the return type of arm_smmu_install_ste_for_dev
|
|
to void, to make it explicit that it cannot fail.
|
|
|
|
Signed-off-by: Will Deacon <will.deacon@arm.com>
|
|
(cherry picked from commit 67560edcd8e5c57eccec4df562abbfc21c17ad75)
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/iommu/arm-smmu-v3.c | 12 +++---------
|
|
1 file changed, 3 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
|
|
index b47a88757c18..97be8de3e834 100644
|
|
--- a/drivers/iommu/arm-smmu-v3.c
|
|
+++ b/drivers/iommu/arm-smmu-v3.c
|
|
@@ -1579,7 +1579,7 @@ static __le64 *arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid)
|
|
return step;
|
|
}
|
|
|
|
-static int arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec)
|
|
+static void arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec)
|
|
{
|
|
int i;
|
|
struct arm_smmu_master_data *master = fwspec->iommu_priv;
|
|
@@ -1591,8 +1591,6 @@ static int arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec)
|
|
|
|
arm_smmu_write_strtab_ent(smmu, sid, step, &master->ste);
|
|
}
|
|
-
|
|
- return 0;
|
|
}
|
|
|
|
static void arm_smmu_detach_dev(struct device *dev)
|
|
@@ -1600,8 +1598,7 @@ static void arm_smmu_detach_dev(struct device *dev)
|
|
struct arm_smmu_master_data *master = dev->iommu_fwspec->iommu_priv;
|
|
|
|
master->ste.bypass = true;
|
|
- if (arm_smmu_install_ste_for_dev(dev->iommu_fwspec) < 0)
|
|
- dev_warn(dev, "failed to install bypass STE\n");
|
|
+ arm_smmu_install_ste_for_dev(dev->iommu_fwspec);
|
|
}
|
|
|
|
static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
|
|
@@ -1653,10 +1650,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
|
|
ste->s2_cfg = &smmu_domain->s2_cfg;
|
|
}
|
|
|
|
- ret = arm_smmu_install_ste_for_dev(dev->iommu_fwspec);
|
|
- if (ret < 0)
|
|
- ste->valid = false;
|
|
-
|
|
+ arm_smmu_install_ste_for_dev(dev->iommu_fwspec);
|
|
out_unlock:
|
|
mutex_unlock(&smmu_domain->init_mutex);
|
|
return ret;
|
|
--
|
|
2.11.0
|
|
|
|
From 2e7b81f22936290d872bc624599f7c25f7513829 Mon Sep 17 00:00:00 2001
|
|
From: Will Deacon <will.deacon@arm.com>
|
|
Date: Fri, 6 Jan 2017 16:27:30 +0000
|
|
Subject: [PATCH 24/41] iommu/arm-smmu-v3: Install bypass STEs for
|
|
IOMMU_DOMAIN_IDENTITY domains
|
|
|
|
In preparation for allowing the default domain type to be overridden,
|
|
this patch adds support for IOMMU_DOMAIN_IDENTITY domains to the
|
|
ARM SMMUv3 driver.
|
|
|
|
An identity domain is created by placing the corresponding stream table
|
|
entries into "bypass" mode, which allows transactions to flow through
|
|
the SMMU without any translation.
|
|
|
|
Signed-off-by: Will Deacon <will.deacon@arm.com>
|
|
(cherry picked from commit beb3c6a066bff1ba412f983cb9d1a42f4cd8f76a)
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/iommu/arm-smmu-v3.c | 58 +++++++++++++++++++++++++++++----------------
|
|
1 file changed, 37 insertions(+), 21 deletions(-)
|
|
|
|
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
|
|
index 97be8de3e834..803352d78d43 100644
|
|
--- a/drivers/iommu/arm-smmu-v3.c
|
|
+++ b/drivers/iommu/arm-smmu-v3.c
|
|
@@ -554,9 +554,14 @@ struct arm_smmu_s2_cfg {
|
|
};
|
|
|
|
struct arm_smmu_strtab_ent {
|
|
- bool valid;
|
|
-
|
|
- bool bypass; /* Overrides s1/s2 config */
|
|
+ /*
|
|
+ * An STE is "assigned" if the master emitting the corresponding SID
|
|
+ * is attached to a domain. The behaviour of an unassigned STE is
|
|
+ * determined by the disable_bypass parameter, whereas an assigned
|
|
+ * STE behaves according to s1_cfg/s2_cfg, which themselves are
|
|
+ * configured according to the domain type.
|
|
+ */
|
|
+ bool assigned;
|
|
struct arm_smmu_s1_cfg *s1_cfg;
|
|
struct arm_smmu_s2_cfg *s2_cfg;
|
|
};
|
|
@@ -632,6 +637,7 @@ enum arm_smmu_domain_stage {
|
|
ARM_SMMU_DOMAIN_S1 = 0,
|
|
ARM_SMMU_DOMAIN_S2,
|
|
ARM_SMMU_DOMAIN_NESTED,
|
|
+ ARM_SMMU_DOMAIN_BYPASS,
|
|
};
|
|
|
|
struct arm_smmu_domain {
|
|
@@ -1005,9 +1011,9 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid,
|
|
* This is hideously complicated, but we only really care about
|
|
* three cases at the moment:
|
|
*
|
|
- * 1. Invalid (all zero) -> bypass (init)
|
|
- * 2. Bypass -> translation (attach)
|
|
- * 3. Translation -> bypass (detach)
|
|
+ * 1. Invalid (all zero) -> bypass/fault (init)
|
|
+ * 2. Bypass/fault -> translation/bypass (attach)
|
|
+ * 3. Translation/bypass -> bypass/fault (detach)
|
|
*
|
|
* Given that we can't update the STE atomically and the SMMU
|
|
* doesn't read the thing in a defined order, that leaves us
|
|
@@ -1046,11 +1052,15 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid,
|
|
}
|
|
|
|
/* Nuke the existing STE_0 value, as we're going to rewrite it */
|
|
- val = ste->valid ? STRTAB_STE_0_V : 0;
|
|
+ val = STRTAB_STE_0_V;
|
|
+
|
|
+ /* Bypass/fault */
|
|
+ if (!ste->assigned || !(ste->s1_cfg || ste->s2_cfg)) {
|
|
+ if (!ste->assigned && disable_bypass)
|
|
+ val |= STRTAB_STE_0_CFG_ABORT;
|
|
+ else
|
|
+ val |= STRTAB_STE_0_CFG_BYPASS;
|
|
|
|
- if (ste->bypass) {
|
|
- val |= disable_bypass ? STRTAB_STE_0_CFG_ABORT
|
|
- : STRTAB_STE_0_CFG_BYPASS;
|
|
dst[0] = cpu_to_le64(val);
|
|
dst[1] = cpu_to_le64(STRTAB_STE_1_SHCFG_INCOMING
|
|
<< STRTAB_STE_1_SHCFG_SHIFT);
|
|
@@ -1111,10 +1121,7 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid,
|
|
static void arm_smmu_init_bypass_stes(u64 *strtab, unsigned int nent)
|
|
{
|
|
unsigned int i;
|
|
- struct arm_smmu_strtab_ent ste = {
|
|
- .valid = true,
|
|
- .bypass = true,
|
|
- };
|
|
+ struct arm_smmu_strtab_ent ste = { .assigned = false };
|
|
|
|
for (i = 0; i < nent; ++i) {
|
|
arm_smmu_write_strtab_ent(NULL, -1, strtab, &ste);
|
|
@@ -1378,7 +1385,9 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
|
|
{
|
|
struct arm_smmu_domain *smmu_domain;
|
|
|
|
- if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
|
|
+ if (type != IOMMU_DOMAIN_UNMANAGED &&
|
|
+ type != IOMMU_DOMAIN_DMA &&
|
|
+ type != IOMMU_DOMAIN_IDENTITY)
|
|
return NULL;
|
|
|
|
/*
|
|
@@ -1509,6 +1518,11 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain)
|
|
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
|
|
struct arm_smmu_device *smmu = smmu_domain->smmu;
|
|
|
|
+ if (domain->type == IOMMU_DOMAIN_IDENTITY) {
|
|
+ smmu_domain->stage = ARM_SMMU_DOMAIN_BYPASS;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
/* Restrict the stage to what we can actually support */
|
|
if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S1))
|
|
smmu_domain->stage = ARM_SMMU_DOMAIN_S2;
|
|
@@ -1597,7 +1611,7 @@ static void arm_smmu_detach_dev(struct device *dev)
|
|
{
|
|
struct arm_smmu_master_data *master = dev->iommu_fwspec->iommu_priv;
|
|
|
|
- master->ste.bypass = true;
|
|
+ master->ste.assigned = false;
|
|
arm_smmu_install_ste_for_dev(dev->iommu_fwspec);
|
|
}
|
|
|
|
@@ -1617,7 +1631,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
|
|
ste = &master->ste;
|
|
|
|
/* Already attached to a different domain? */
|
|
- if (!ste->bypass)
|
|
+ if (ste->assigned)
|
|
arm_smmu_detach_dev(dev);
|
|
|
|
mutex_lock(&smmu_domain->init_mutex);
|
|
@@ -1638,10 +1652,12 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
|
|
goto out_unlock;
|
|
}
|
|
|
|
- ste->bypass = false;
|
|
- ste->valid = true;
|
|
+ ste->assigned = true;
|
|
|
|
- if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
|
|
+ if (smmu_domain->stage == ARM_SMMU_DOMAIN_BYPASS) {
|
|
+ ste->s1_cfg = NULL;
|
|
+ ste->s2_cfg = NULL;
|
|
+ } else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
|
|
ste->s1_cfg = &smmu_domain->s1_cfg;
|
|
ste->s2_cfg = NULL;
|
|
arm_smmu_write_ctx_desc(smmu, ste->s1_cfg);
|
|
@@ -1801,7 +1817,7 @@ static void arm_smmu_remove_device(struct device *dev)
|
|
|
|
master = fwspec->iommu_priv;
|
|
smmu = master->smmu;
|
|
- if (master && master->ste.valid)
|
|
+ if (master && master->ste.assigned)
|
|
arm_smmu_detach_dev(dev);
|
|
iommu_group_remove_device(dev);
|
|
iommu_device_unlink(&smmu->iommu, dev);
|
|
--
|
|
2.11.0
|
|
|
|
From ed65b7b197ed312ee0aa1d347240061dbc8fd4cf Mon Sep 17 00:00:00 2001
|
|
From: Will Deacon <will.deacon@arm.com>
|
|
Date: Thu, 5 Jan 2017 18:38:26 +0000
|
|
Subject: [PATCH 25/41] iommu: Allow default domain type to be set on the
|
|
kernel command line
|
|
|
|
The IOMMU core currently initialises the default domain for each group
|
|
to IOMMU_DOMAIN_DMA, under the assumption that devices will use
|
|
IOMMU-backed DMA ops by default. However, in some cases it is desirable
|
|
for the DMA ops to bypass the IOMMU for performance reasons, reserving
|
|
use of translation for subsystems such as VFIO that require it for
|
|
enforcing device isolation.
|
|
|
|
Rather than modify each IOMMU driver to provide different semantics for
|
|
DMA domains, instead we introduce a command line parameter that can be
|
|
used to change the type of the default domain. Passthrough can then be
|
|
specified using "iommu.passthrough=1" on the kernel command line.
|
|
|
|
Signed-off-by: Will Deacon <will.deacon@arm.com>
|
|
(cherry picked from commit fccb4e3b8ab0957628abec82675691c72f67003e)
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
Documentation/admin-guide/kernel-parameters.txt | 6 ++++++
|
|
drivers/iommu/iommu.c | 28 ++++++++++++++++++++++---
|
|
2 files changed, 31 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
|
|
index facc20a3f962..cb91f26cc8bc 100644
|
|
--- a/Documentation/admin-guide/kernel-parameters.txt
|
|
+++ b/Documentation/admin-guide/kernel-parameters.txt
|
|
@@ -1644,6 +1644,12 @@
|
|
nobypass [PPC/POWERNV]
|
|
Disable IOMMU bypass, using IOMMU for PCI devices.
|
|
|
|
+ iommu.passthrough=
|
|
+ [ARM64] Configure DMA to bypass the IOMMU by default.
|
|
+ Format: { "0" | "1" }
|
|
+ 0 - Use IOMMU translation for DMA.
|
|
+ 1 - Bypass the IOMMU for DMA.
|
|
+ unset - Use IOMMU translation for DMA.
|
|
|
|
io7= [HW] IO7 for Marvel based alpha systems
|
|
See comment before marvel_specify_io7 in
|
|
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
|
|
index 3b67144dead2..770ba7e7ef4d 100644
|
|
--- a/drivers/iommu/iommu.c
|
|
+++ b/drivers/iommu/iommu.c
|
|
@@ -36,6 +36,7 @@
|
|
|
|
static struct kset *iommu_group_kset;
|
|
static DEFINE_IDA(iommu_group_ida);
|
|
+static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_DMA;
|
|
|
|
struct iommu_callback_data {
|
|
const struct iommu_ops *ops;
|
|
@@ -112,6 +113,18 @@ static int __iommu_attach_group(struct iommu_domain *domain,
|
|
static void __iommu_detach_group(struct iommu_domain *domain,
|
|
struct iommu_group *group);
|
|
|
|
+static int __init iommu_set_def_domain_type(char *str)
|
|
+{
|
|
+ bool pt;
|
|
+
|
|
+ if (!str || strtobool(str, &pt))
|
|
+ return -EINVAL;
|
|
+
|
|
+ iommu_def_domain_type = pt ? IOMMU_DOMAIN_IDENTITY : IOMMU_DOMAIN_DMA;
|
|
+ return 0;
|
|
+}
|
|
+early_param("iommu.passthrough", iommu_set_def_domain_type);
|
|
+
|
|
static ssize_t iommu_group_attr_show(struct kobject *kobj,
|
|
struct attribute *__attr, char *buf)
|
|
{
|
|
@@ -1015,10 +1028,19 @@ struct iommu_group *iommu_group_get_for_dev(struct device *dev)
|
|
* IOMMU driver.
|
|
*/
|
|
if (!group->default_domain) {
|
|
- group->default_domain = __iommu_domain_alloc(dev->bus,
|
|
- IOMMU_DOMAIN_DMA);
|
|
+ struct iommu_domain *dom;
|
|
+
|
|
+ dom = __iommu_domain_alloc(dev->bus, iommu_def_domain_type);
|
|
+ if (!dom && iommu_def_domain_type != IOMMU_DOMAIN_DMA) {
|
|
+ dev_warn(dev,
|
|
+ "failed to allocate default IOMMU domain of type %u; falling back to IOMMU_DOMAIN_DMA",
|
|
+ iommu_def_domain_type);
|
|
+ dom = __iommu_domain_alloc(dev->bus, IOMMU_DOMAIN_DMA);
|
|
+ }
|
|
+
|
|
+ group->default_domain = dom;
|
|
if (!group->domain)
|
|
- group->domain = group->default_domain;
|
|
+ group->domain = dom;
|
|
}
|
|
|
|
ret = iommu_group_add_device(group, dev);
|
|
--
|
|
2.11.0
|
|
|
|
From 11eb465df795bea2c26cb3877ceb606336406a32 Mon Sep 17 00:00:00 2001
|
|
From: Robert Richter <rrichter@cavium.com>
|
|
Date: Wed, 12 Apr 2017 15:06:03 +0200
|
|
Subject: [PATCH 26/41] iommu: Print a message with the default domain type
|
|
created
|
|
|
|
There are several ways the bypass mode can be enabled. With commit
|
|
|
|
fccb4e3b8ab0 iommu: Allow default domain type to be set on the kernel command line
|
|
|
|
there is the option to switch into bypass mode. And, depending on
|
|
devicetree options, bypass mode can be also enabled. This makes it
|
|
hard to determine if direct mapping is enabled. Print message with the
|
|
default domain type case.
|
|
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/iommu/iommu.c | 4 +++-
|
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
|
|
index 770ba7e7ef4d..b698732c6f91 100644
|
|
--- a/drivers/iommu/iommu.c
|
|
+++ b/drivers/iommu/iommu.c
|
|
@@ -599,7 +599,9 @@ int iommu_group_add_device(struct iommu_group *group, struct device *dev)
|
|
|
|
trace_add_device_to_group(group->id, dev);
|
|
|
|
- pr_info("Adding device %s to group %d\n", dev_name(dev), group->id);
|
|
+ pr_info("Adding device %s to group %d, default domain type %d\n",
|
|
+ dev_name(dev), group->id,
|
|
+ group->default_domain ? group->default_domain->type : -1);
|
|
|
|
return 0;
|
|
|
|
--
|
|
2.11.0
|
|
|
|
From 8045df4924b41d303cd0599f1ed1ff9b23bed036 Mon Sep 17 00:00:00 2001
|
|
From: Sunil Goutham <sgoutham@cavium.com>
|
|
Date: Tue, 25 Apr 2017 15:27:52 +0530
|
|
Subject: [PATCH 27/41] iommu/arm-smmu: Return IOVA in iova_to_phys when SMMU
|
|
is bypassed
|
|
|
|
For software initiated address translation, when domain type is
|
|
IOMMU_DOMAIN_IDENTITY i.e SMMU is bypassed, mimic HW behavior
|
|
i.e return the same IOVA as translated address.
|
|
|
|
This patch is an extension to Will Deacon's patchset
|
|
"Implement SMMU passthrough using the default domain".
|
|
|
|
Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
|
|
Acked-by: Will Deacon <will.deacon@arm.com>
|
|
Signed-off-by: Joerg Roedel <jroedel@suse.de>
|
|
(cherry picked from commit bdf95923086fb359ccb44c815724c3ace1611c90)
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/iommu/arm-smmu-v3.c | 3 +++
|
|
drivers/iommu/arm-smmu.c | 3 +++
|
|
2 files changed, 6 insertions(+)
|
|
|
|
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
|
|
index 803352d78d43..6ef9c3ed4344 100644
|
|
--- a/drivers/iommu/arm-smmu-v3.c
|
|
+++ b/drivers/iommu/arm-smmu-v3.c
|
|
@@ -1714,6 +1714,9 @@ arm_smmu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
|
|
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
|
|
struct io_pgtable_ops *ops = smmu_domain->pgtbl_ops;
|
|
|
|
+ if (domain->type == IOMMU_DOMAIN_IDENTITY)
|
|
+ return iova;
|
|
+
|
|
if (!ops)
|
|
return 0;
|
|
|
|
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
|
|
index 88e9131b6900..e731d8ead6cc 100644
|
|
--- a/drivers/iommu/arm-smmu.c
|
|
+++ b/drivers/iommu/arm-smmu.c
|
|
@@ -1411,6 +1411,9 @@ static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
|
|
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
|
|
struct io_pgtable_ops *ops= smmu_domain->pgtbl_ops;
|
|
|
|
+ if (domain->type == IOMMU_DOMAIN_IDENTITY)
|
|
+ return iova;
|
|
+
|
|
if (!ops)
|
|
return 0;
|
|
|
|
--
|
|
2.11.0
|
|
|
|
From fecd86ffe12e5c49f22325faf732eaf5cfe8c62b Mon Sep 17 00:00:00 2001
|
|
From: Robert Richter <rrichter@cavium.com>
|
|
Date: Thu, 4 May 2017 17:48:48 +0200
|
|
Subject: [PATCH 28/41] iommu, aarch64: Set bypass mode per default
|
|
|
|
We see a performance degradation if smmu is enabled in non-bypass mode.
|
|
This is a problem in the kernel's implememntation. Until that is solved,
|
|
enable smmu in bypass mode per default.
|
|
|
|
We have tested that SMMU passthrough mode doesn't effect VFIO on both
|
|
CN88xx and CN99xx and haven't found any issues.
|
|
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/iommu/iommu.c | 5 +++++
|
|
1 file changed, 5 insertions(+)
|
|
|
|
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
|
|
index b698732c6f91..41125b19832b 100644
|
|
--- a/drivers/iommu/iommu.c
|
|
+++ b/drivers/iommu/iommu.c
|
|
@@ -36,7 +36,12 @@
|
|
|
|
static struct kset *iommu_group_kset;
|
|
static DEFINE_IDA(iommu_group_ida);
|
|
+
|
|
+#ifdef CONFIG_ARM64
|
|
+static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_IDENTITY;
|
|
+#else
|
|
static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_DMA;
|
|
+#endif
|
|
|
|
struct iommu_callback_data {
|
|
const struct iommu_ops *ops;
|
|
--
|
|
2.11.0
|
|
|
|
From patchwork Mon May 22 15:06:37 2017
|
|
Content-Type: text/plain; charset="utf-8"
|
|
MIME-Version: 1.0
|
|
Content-Transfer-Encoding: 7bit
|
|
Subject: [v2,1/2] ACPICA: IORT: Update SMMU models for IORT rev. C
|
|
From: Robin Murphy <robin.murphy@arm.com>
|
|
X-Patchwork-Id: 9740941
|
|
Message-Id: <11ef7d28c535c01d42b7b3c8e632934f0e0f1048.1495459319.git.robin.murphy@arm.com>
|
|
To: will.deacon@arm.com,
|
|
joro@8bytes.org
|
|
Cc: lorenzo.pieralisi@arm.com, gabriele.paoloni@huawei.com,
|
|
gakula@caviumnetworks.com, rjw@rjwysocki.net, robert.moore@intel.com,
|
|
shameerali.kolothum.thodi@huawei.com, rrichter@cavium.com,
|
|
linux-acpi@vger.kernel.org, iommu@lists.linux-foundation.org,
|
|
hanjun.guo@linaro.org, linu.cherian@cavium.com, john.garry@huawei.com,
|
|
linux-arm-kernel@lists.infradead.org, lv.zheng@intel.com
|
|
Date: Mon, 22 May 2017 16:06:37 +0100
|
|
|
|
IORT revision C has been published with a number of new SMMU
|
|
implementation identifiers. Since IORT doesn't have any way of falling
|
|
back to a more generic model code, we really need Linux to know about
|
|
these before vendors start updating their firmware tables to use them.
|
|
|
|
CC: Rafael J. Wysocki <rjw@rjwysocki.net>
|
|
CC: Robert Moore <robert.moore@intel.com>
|
|
CC: Lv Zheng <lv.zheng@intel.com>
|
|
Acked-by: Robert Richter <rrichter@cavium.com>
|
|
Tested-by: Robert Richter <rrichter@cavium.com>
|
|
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
|
|
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
|
|
---
|
|
|
|
v2: Update more comments, add Robert's tags.
|
|
|
|
I'm including this here as a kernel patch just for context - once I've
|
|
figured out how we actually submit patches to ACPICA directly, I'll do
|
|
that per the preferred process.
|
|
|
|
Robin.
|
|
|
|
include/acpi/actbl2.h | 12 ++++++++++--
|
|
1 file changed, 10 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
|
|
index faa9f2c0d5de..f469ea41f2fd 100644
|
|
--- a/include/acpi/actbl2.h
|
|
+++ b/include/acpi/actbl2.h
|
|
@@ -663,7 +663,7 @@ struct acpi_ibft_target {
|
|
* IORT - IO Remapping Table
|
|
*
|
|
* Conforms to "IO Remapping Table System Software on ARM Platforms",
|
|
- * Document number: ARM DEN 0049B, October 2015
|
|
+ * Document number: ARM DEN 0049C, May 2017
|
|
*
|
|
******************************************************************************/
|
|
|
|
@@ -778,6 +778,8 @@ struct acpi_iort_smmu {
|
|
#define ACPI_IORT_SMMU_V2 0x00000001 /* Generic SMMUv2 */
|
|
#define ACPI_IORT_SMMU_CORELINK_MMU400 0x00000002 /* ARM Corelink MMU-400 */
|
|
#define ACPI_IORT_SMMU_CORELINK_MMU500 0x00000003 /* ARM Corelink MMU-500 */
|
|
+#define ACPI_IORT_SMMU_CORELINK_MMU401 0x00000004 /* ARM Corelink MMU-401 */
|
|
+#define ACPI_IORT_SMMU_CAVIUM_SMMUV2 0x00000005 /* Cavium ThunderX SMMUv2 */
|
|
|
|
/* Masks for Flags field above */
|
|
|
|
@@ -798,13 +800,19 @@ struct acpi_iort_smmu_v3 {
|
|
u32 flags;
|
|
u32 reserved;
|
|
u64 vatos_address;
|
|
- u32 model; /* O: generic SMMUv3 */
|
|
+ u32 model;
|
|
u32 event_gsiv;
|
|
u32 pri_gsiv;
|
|
u32 gerr_gsiv;
|
|
u32 sync_gsiv;
|
|
};
|
|
|
|
+/* Values for Model field above */
|
|
+
|
|
+#define ACPI_IORT_SMMU_V3 0x00000000 /* Generic SMMUv3 */
|
|
+#define ACPI_IORT_SMMU_HISILICON_HI161X 0x00000001 /* HiSilicon Hi161x SMMUv3 */
|
|
+#define ACPI_IORT_SMMU_CAVIUM_CN99XX 0x00000002 /* Cavium CN99xx SMMUv3 */
|
|
+
|
|
/* Masks for Flags field above */
|
|
|
|
#define ACPI_IORT_SMMU_V3_COHACC_OVERRIDE (1)
|
|
From patchwork Mon May 22 15:06:38 2017
|
|
Content-Type: text/plain; charset="utf-8"
|
|
MIME-Version: 1.0
|
|
Content-Transfer-Encoding: 7bit
|
|
Subject: [v2,2/2] iommu/arm-smmu: Plumb in new ACPI identifiers
|
|
From: Robin Murphy <robin.murphy@arm.com>
|
|
X-Patchwork-Id: 9740939
|
|
Message-Id: <ac4e7adc7ca636fc71e6a10f0d8ab273b3dfd5dc.1495459319.git.robin.murphy@arm.com>
|
|
To: will.deacon@arm.com,
|
|
joro@8bytes.org
|
|
Cc: lorenzo.pieralisi@arm.com, gabriele.paoloni@huawei.com,
|
|
gakula@caviumnetworks.com, shameerali.kolothum.thodi@huawei.com,
|
|
rrichter@cavium.com, linux-acpi@vger.kernel.org,
|
|
iommu@lists.linux-foundation.org, hanjun.guo@linaro.org,
|
|
linu.cherian@cavium.com, stable@vger.kernel.org, john.garry@huawei.com,
|
|
linux-arm-kernel@lists.infradead.org
|
|
Date: Mon, 22 May 2017 16:06:38 +0100
|
|
|
|
Revision C of IORT now allows us to identify ARM MMU-401 and the Cavium
|
|
ThunderX implementation. Wire them up so that we can probe these models
|
|
once firmware starts using the new codes, and so that the appropriate
|
|
features and quirks get enabled when we do.
|
|
|
|
For the sake of backports and mitigating sychronisation problems with
|
|
the ACPICA headers, we'll carry a backup copy of the new definitions
|
|
locally for the short term to make life simpler.
|
|
|
|
CC: stable@vger.kernel.org # 4.10
|
|
Acked-by: Robert Richter <rrichter@cavium.com>
|
|
Tested-by: Robert Richter <rrichter@cavium.com>
|
|
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
|
|
---
|
|
|
|
v2: Add local backup definitions
|
|
|
|
This is ready to go regardless of patch 1. The stable backport is in likely
|
|
anticipation of machines with updated firmware paired with stable distro
|
|
kernels, which would be unable to recognise and probe the SMMU otherwise.
|
|
|
|
Robin.
|
|
|
|
drivers/iommu/arm-smmu.c | 16 ++++++++++++++++
|
|
1 file changed, 16 insertions(+)
|
|
|
|
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
|
|
index 7ec30b08b3bd..79b9bb7d4783 100644
|
|
--- a/drivers/iommu/arm-smmu.c
|
|
+++ b/drivers/iommu/arm-smmu.c
|
|
@@ -312,6 +312,14 @@ enum arm_smmu_implementation {
|
|
CAVIUM_SMMUV2,
|
|
};
|
|
|
|
+/* Until ACPICA headers cover IORT rev. C */
|
|
+#ifndef ACPI_IORT_SMMU_CORELINK_MMU401
|
|
+#define ACPI_IORT_SMMU_CORELINK_MMU401 0x4
|
|
+#endif
|
|
+#ifndef ACPI_IORT_SMMU_CAVIUM_SMMUV2
|
|
+#define ACPI_IORT_SMMU_CAVIUM_SMMUV2 0x5
|
|
+#endif
|
|
+
|
|
struct arm_smmu_s2cr {
|
|
struct iommu_group *group;
|
|
int count;
|
|
@@ -2073,6 +2081,10 @@ static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu)
|
|
smmu->version = ARM_SMMU_V1;
|
|
smmu->model = GENERIC_SMMU;
|
|
break;
|
|
+ case ACPI_IORT_SMMU_CORELINK_MMU401:
|
|
+ smmu->version = ARM_SMMU_V1_64K;
|
|
+ smmu->model = GENERIC_SMMU;
|
|
+ break;
|
|
case ACPI_IORT_SMMU_V2:
|
|
smmu->version = ARM_SMMU_V2;
|
|
smmu->model = GENERIC_SMMU;
|
|
@@ -2081,6 +2093,10 @@ static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu)
|
|
smmu->version = ARM_SMMU_V2;
|
|
smmu->model = ARM_MMU500;
|
|
break;
|
|
+ case ACPI_IORT_SMMU_CAVIUM_SMMUV2:
|
|
+ smmu->version = ARM_SMMU_V2;
|
|
+ smmu->model = CAVIUM_SMMUV2;
|
|
+ break;
|
|
default:
|
|
ret = -ENODEV;
|
|
}
|
|
From 980ec2906ad4e92a89e8f635a79eba90318b22d5 Mon Sep 17 00:00:00 2001
|
|
From: Linu Cherian <linu.cherian@cavium.com>
|
|
Date: Fri, 12 May 2017 18:11:04 +0530
|
|
Subject: [PATCH 31/41] ACPI/IORT: Fixup SMMUv3 resource size for Cavium
|
|
ThunderX2 SMMUv3 model
|
|
|
|
Cavium ThunderX2 implementation doesn't support second page in SMMU
|
|
register space. Hence, resource size is set as 64k for this model.
|
|
|
|
Signed-off-by: Linu Cherian <linu.cherian@cavium.com>
|
|
Signed-off-by: Geetha Sowjanya <geethasowjanya.akula@cavium.com>
|
|
Message-Id: <1494592866-14076-2-git-send-email-gakula@caviumnetworks.com>
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/acpi/arm64/iort.c | 10 +++++++++-
|
|
1 file changed, 9 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
|
|
index 4a5bb967250b..9fd2f1d31a27 100644
|
|
--- a/drivers/acpi/arm64/iort.c
|
|
+++ b/drivers/acpi/arm64/iort.c
|
|
@@ -669,12 +669,20 @@ static void __init arm_smmu_v3_init_resources(struct resource *res,
|
|
{
|
|
struct acpi_iort_smmu_v3 *smmu;
|
|
int num_res = 0;
|
|
+ unsigned long size = SZ_128K;
|
|
|
|
/* Retrieve SMMUv3 specific data */
|
|
smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
|
|
|
|
+ /*
|
|
+ * Override the size, for Cavium ThunderX2 implementation
|
|
+ * which doesn't support the page 1 SMMU register space.
|
|
+ */
|
|
+ if (smmu->model == ACPI_IORT_SMMU_CAVIUM_CN99XX)
|
|
+ size = SZ_64K;
|
|
+
|
|
res[num_res].start = smmu->base_address;
|
|
- res[num_res].end = smmu->base_address + SZ_128K - 1;
|
|
+ res[num_res].end = smmu->base_address + size - 1;
|
|
res[num_res].flags = IORESOURCE_MEM;
|
|
|
|
num_res++;
|
|
--
|
|
2.11.0
|
|
|
|
From d082f66524ad8653793fc753dbff2b369b3cafe8 Mon Sep 17 00:00:00 2001
|
|
From: Linu Cherian <linu.cherian@cavium.com>
|
|
Date: Fri, 12 May 2017 18:11:05 +0530
|
|
Subject: [PATCH 32/41] iommu/arm-smmu-v3: Add workaround for Cavium ThunderX2
|
|
erratum #74
|
|
|
|
Cavium ThunderX2 SMMU implementation doesn't support page 1 register space
|
|
and PAGE0_REGS_ONLY option is enabled as an errata workaround.
|
|
This option when turned on, replaces all page 1 offsets used for
|
|
EVTQ_PROD/CONS, PRIQ_PROD/CONS register access with page 0 offsets.
|
|
|
|
SMMU resource size checks are now based on SMMU option PAGE0_REGS_ONLY,
|
|
since resource size can be either 64k/128k.
|
|
For this, arm_smmu_device_dt_probe/acpi_probe has been moved before
|
|
platform_get_resource call, so that SMMU options are set beforehand.
|
|
|
|
Signed-off-by: Linu Cherian <linu.cherian@cavium.com>
|
|
Signed-off-by: Geetha Sowjanya <geethasowjanya.akula@cavium.com>
|
|
Message-Id: <1494592866-14076-3-git-send-email-gakula@caviumnetworks.com>
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
Documentation/arm64/silicon-errata.txt | 1 +
|
|
.../devicetree/bindings/iommu/arm,smmu-v3.txt | 6 ++
|
|
drivers/iommu/arm-smmu-v3.c | 64 +++++++++++++++++-----
|
|
3 files changed, 56 insertions(+), 15 deletions(-)
|
|
|
|
diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
|
|
index 2f66683500b8..629e2ce1f0d2 100644
|
|
--- a/Documentation/arm64/silicon-errata.txt
|
|
+++ b/Documentation/arm64/silicon-errata.txt
|
|
@@ -61,6 +61,7 @@ stable kernels.
|
|
| Cavium | ThunderX GICv3 | #23154 | CAVIUM_ERRATUM_23154 |
|
|
| Cavium | ThunderX Core | #27456 | CAVIUM_ERRATUM_27456 |
|
|
| Cavium | ThunderX SMMUv2 | #27704 | N/A |
|
|
+| Cavium | ThunderX2 SMMUv3| #74 | N/A |
|
|
| | | | |
|
|
| Freescale/NXP | LS2080A/LS1043A | A-008585 | FSL_ERRATUM_A008585 |
|
|
| | | | |
|
|
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
|
|
index be57550e14e4..e6da62b3a3ff 100644
|
|
--- a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
|
|
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
|
|
@@ -49,6 +49,12 @@ the PCIe specification.
|
|
- hisilicon,broken-prefetch-cmd
|
|
: Avoid sending CMD_PREFETCH_* commands to the SMMU.
|
|
|
|
+- cavium-cn99xx,broken-page1-regspace
|
|
+ : Replaces all page 1 offsets used for EVTQ_PROD/CONS,
|
|
+ PRIQ_PROD/CONS register access with page 0 offsets.
|
|
+ Set for Caviun ThunderX2 silicon that doesn't support
|
|
+ SMMU page1 register space.
|
|
+
|
|
** Example
|
|
|
|
smmu@2b400000 {
|
|
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
|
|
index 6ef9c3ed4344..913805429f80 100644
|
|
--- a/drivers/iommu/arm-smmu-v3.c
|
|
+++ b/drivers/iommu/arm-smmu-v3.c
|
|
@@ -412,6 +412,9 @@
|
|
#define MSI_IOVA_BASE 0x8000000
|
|
#define MSI_IOVA_LENGTH 0x100000
|
|
|
|
+#define ARM_SMMU_PAGE0_REGS_ONLY(smmu) \
|
|
+ ((smmu)->options & ARM_SMMU_OPT_PAGE0_REGS_ONLY)
|
|
+
|
|
static bool disable_bypass;
|
|
module_param_named(disable_bypass, disable_bypass, bool, S_IRUGO);
|
|
MODULE_PARM_DESC(disable_bypass,
|
|
@@ -597,6 +600,7 @@ struct arm_smmu_device {
|
|
u32 features;
|
|
|
|
#define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0)
|
|
+#define ARM_SMMU_OPT_PAGE0_REGS_ONLY (1 << 1)
|
|
u32 options;
|
|
|
|
struct arm_smmu_cmdq cmdq;
|
|
@@ -663,9 +667,19 @@ struct arm_smmu_option_prop {
|
|
|
|
static struct arm_smmu_option_prop arm_smmu_options[] = {
|
|
{ ARM_SMMU_OPT_SKIP_PREFETCH, "hisilicon,broken-prefetch-cmd" },
|
|
+ { ARM_SMMU_OPT_PAGE0_REGS_ONLY, "cavium-cn99xx,broken-page1-regspace"},
|
|
{ 0, NULL},
|
|
};
|
|
|
|
+static inline void __iomem *arm_smmu_page1_fixup(unsigned long offset,
|
|
+ struct arm_smmu_device *smmu)
|
|
+{
|
|
+ if (offset > SZ_64K && ARM_SMMU_PAGE0_REGS_ONLY(smmu))
|
|
+ offset -= SZ_64K;
|
|
+
|
|
+ return smmu->base + offset;
|
|
+}
|
|
+
|
|
static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
|
|
{
|
|
return container_of(dom, struct arm_smmu_domain, domain);
|
|
@@ -1959,8 +1973,8 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
|
|
return -ENOMEM;
|
|
}
|
|
|
|
- q->prod_reg = smmu->base + prod_off;
|
|
- q->cons_reg = smmu->base + cons_off;
|
|
+ q->prod_reg = arm_smmu_page1_fixup(prod_off, smmu);
|
|
+ q->cons_reg = arm_smmu_page1_fixup(cons_off, smmu);
|
|
q->ent_dwords = dwords;
|
|
|
|
q->q_base = Q_BASE_RWA;
|
|
@@ -2361,8 +2375,10 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
|
|
|
|
/* Event queue */
|
|
writeq_relaxed(smmu->evtq.q.q_base, smmu->base + ARM_SMMU_EVTQ_BASE);
|
|
- writel_relaxed(smmu->evtq.q.prod, smmu->base + ARM_SMMU_EVTQ_PROD);
|
|
- writel_relaxed(smmu->evtq.q.cons, smmu->base + ARM_SMMU_EVTQ_CONS);
|
|
+ writel_relaxed(smmu->evtq.q.prod,
|
|
+ arm_smmu_page1_fixup(ARM_SMMU_EVTQ_PROD, smmu));
|
|
+ writel_relaxed(smmu->evtq.q.cons,
|
|
+ arm_smmu_page1_fixup(ARM_SMMU_EVTQ_CONS, smmu));
|
|
|
|
enables |= CR0_EVTQEN;
|
|
ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
|
|
@@ -2377,9 +2393,9 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
|
|
writeq_relaxed(smmu->priq.q.q_base,
|
|
smmu->base + ARM_SMMU_PRIQ_BASE);
|
|
writel_relaxed(smmu->priq.q.prod,
|
|
- smmu->base + ARM_SMMU_PRIQ_PROD);
|
|
+ arm_smmu_page1_fixup(ARM_SMMU_PRIQ_PROD, smmu));
|
|
writel_relaxed(smmu->priq.q.cons,
|
|
- smmu->base + ARM_SMMU_PRIQ_CONS);
|
|
+ arm_smmu_page1_fixup(ARM_SMMU_PRIQ_CONS, smmu));
|
|
|
|
enables |= CR0_PRIQEN;
|
|
ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
|
|
@@ -2603,6 +2619,14 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
|
|
}
|
|
|
|
#ifdef CONFIG_ACPI
|
|
+static void acpi_smmu_get_options(u32 model, struct arm_smmu_device *smmu)
|
|
+{
|
|
+ if (model == ACPI_IORT_SMMU_CAVIUM_CN99XX)
|
|
+ smmu->options |= ARM_SMMU_OPT_PAGE0_REGS_ONLY;
|
|
+
|
|
+ dev_notice(smmu->dev, "option mask 0x%x\n", smmu->options);
|
|
+}
|
|
+
|
|
static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
|
|
struct arm_smmu_device *smmu)
|
|
{
|
|
@@ -2615,6 +2639,8 @@ static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
|
|
/* Retrieve SMMUv3 specific data */
|
|
iort_smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
|
|
|
|
+ acpi_smmu_get_options(iort_smmu->model, smmu);
|
|
+
|
|
if (iort_smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE)
|
|
smmu->features |= ARM_SMMU_FEAT_COHERENCY;
|
|
|
|
@@ -2650,6 +2676,14 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev,
|
|
return ret;
|
|
}
|
|
|
|
+static unsigned long arm_smmu_resource_size(struct arm_smmu_device *smmu)
|
|
+{
|
|
+ if (ARM_SMMU_PAGE0_REGS_ONLY(smmu))
|
|
+ return SZ_64K;
|
|
+ else
|
|
+ return SZ_128K;
|
|
+}
|
|
+
|
|
static int arm_smmu_device_probe(struct platform_device *pdev)
|
|
{
|
|
int irq, ret;
|
|
@@ -2666,9 +2700,17 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
|
|
}
|
|
smmu->dev = dev;
|
|
|
|
+ if (dev->of_node) {
|
|
+ ret = arm_smmu_device_dt_probe(pdev, smmu);
|
|
+ } else {
|
|
+ ret = arm_smmu_device_acpi_probe(pdev, smmu);
|
|
+ if (ret == -ENODEV)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
/* Base address */
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
- if (resource_size(res) + 1 < SZ_128K) {
|
|
+ if (resource_size(res) + 1 < arm_smmu_resource_size(smmu)) {
|
|
dev_err(dev, "MMIO region too small (%pr)\n", res);
|
|
return -EINVAL;
|
|
}
|
|
@@ -2695,14 +2737,6 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
|
|
if (irq > 0)
|
|
smmu->gerr_irq = irq;
|
|
|
|
- if (dev->of_node) {
|
|
- ret = arm_smmu_device_dt_probe(pdev, smmu);
|
|
- } else {
|
|
- ret = arm_smmu_device_acpi_probe(pdev, smmu);
|
|
- if (ret == -ENODEV)
|
|
- return ret;
|
|
- }
|
|
-
|
|
/* Set bypass mode according to firmware probing result */
|
|
bypass = !!ret;
|
|
|
|
--
|
|
2.11.0
|
|
|
|
From 8b0e69d0a8d5c11ee433c2a110a7d056ad190e1a Mon Sep 17 00:00:00 2001
|
|
From: Geetha Sowjanya <geethasowjanya.akula@cavium.com>
|
|
Date: Fri, 12 May 2017 18:11:06 +0530
|
|
Subject: [PATCH 33/41] iommu/arm-smmu-v3: Add workaround for Cavium ThunderX2
|
|
erratum #126
|
|
|
|
Cavium ThunderX2 SMMU doesn't support MSI and also doesn't have unique irq
|
|
lines for gerror, eventq and cmdq-sync.
|
|
|
|
This patch addresses the issue by checking if any interrupt sources are
|
|
using same irq number, then they are registered as shared irqs.
|
|
|
|
Signed-off-by: Geetha Sowjanya <geethasowjanya.akula@cavium.com>
|
|
Message-Id: <1494592866-14076-4-git-send-email-gakula@caviumnetworks.com>
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
Documentation/arm64/silicon-errata.txt | 1 +
|
|
drivers/iommu/arm-smmu-v3.c | 29 +++++++++++++++++++++++++----
|
|
2 files changed, 26 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
|
|
index 629e2ce1f0d2..cc15f251ce42 100644
|
|
--- a/Documentation/arm64/silicon-errata.txt
|
|
+++ b/Documentation/arm64/silicon-errata.txt
|
|
@@ -62,6 +62,7 @@ stable kernels.
|
|
| Cavium | ThunderX Core | #27456 | CAVIUM_ERRATUM_27456 |
|
|
| Cavium | ThunderX SMMUv2 | #27704 | N/A |
|
|
| Cavium | ThunderX2 SMMUv3| #74 | N/A |
|
|
+| Cavium | ThunderX2 SMMUv3| #126 | N/A |
|
|
| | | | |
|
|
| Freescale/NXP | LS2080A/LS1043A | A-008585 | FSL_ERRATUM_A008585 |
|
|
| | | | |
|
|
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
|
|
index 913805429f80..2fc067f3e199 100644
|
|
--- a/drivers/iommu/arm-smmu-v3.c
|
|
+++ b/drivers/iommu/arm-smmu-v3.c
|
|
@@ -2230,6 +2230,25 @@ static void arm_smmu_setup_msis(struct arm_smmu_device *smmu)
|
|
devm_add_action(dev, arm_smmu_free_msis, dev);
|
|
}
|
|
|
|
+static int get_irq_flags(struct arm_smmu_device *smmu, int irq)
|
|
+{
|
|
+ int match_count = 0;
|
|
+
|
|
+ if (irq == smmu->evtq.q.irq)
|
|
+ match_count++;
|
|
+ if (irq == smmu->cmdq.q.irq)
|
|
+ match_count++;
|
|
+ if (irq == smmu->gerr_irq)
|
|
+ match_count++;
|
|
+ if (irq == smmu->priq.q.irq)
|
|
+ match_count++;
|
|
+
|
|
+ if (match_count > 1)
|
|
+ return IRQF_SHARED | IRQF_ONESHOT;
|
|
+
|
|
+ return IRQF_ONESHOT;
|
|
+}
|
|
+
|
|
static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
|
|
{
|
|
int ret, irq;
|
|
@@ -2250,7 +2269,7 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
|
|
if (irq) {
|
|
ret = devm_request_threaded_irq(smmu->dev, irq, NULL,
|
|
arm_smmu_evtq_thread,
|
|
- IRQF_ONESHOT,
|
|
+ get_irq_flags(smmu, irq),
|
|
"arm-smmu-v3-evtq", smmu);
|
|
if (ret < 0)
|
|
dev_warn(smmu->dev, "failed to enable evtq irq\n");
|
|
@@ -2259,7 +2278,8 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
|
|
irq = smmu->cmdq.q.irq;
|
|
if (irq) {
|
|
ret = devm_request_irq(smmu->dev, irq,
|
|
- arm_smmu_cmdq_sync_handler, 0,
|
|
+ arm_smmu_cmdq_sync_handler,
|
|
+ get_irq_flags(smmu, irq),
|
|
"arm-smmu-v3-cmdq-sync", smmu);
|
|
if (ret < 0)
|
|
dev_warn(smmu->dev, "failed to enable cmdq-sync irq\n");
|
|
@@ -2268,7 +2288,8 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
|
|
irq = smmu->gerr_irq;
|
|
if (irq) {
|
|
ret = devm_request_irq(smmu->dev, irq, arm_smmu_gerror_handler,
|
|
- 0, "arm-smmu-v3-gerror", smmu);
|
|
+ get_irq_flags(smmu, irq),
|
|
+ "arm-smmu-v3-gerror", smmu);
|
|
if (ret < 0)
|
|
dev_warn(smmu->dev, "failed to enable gerror irq\n");
|
|
}
|
|
@@ -2278,7 +2299,7 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
|
|
if (irq) {
|
|
ret = devm_request_threaded_irq(smmu->dev, irq, NULL,
|
|
arm_smmu_priq_thread,
|
|
- IRQF_ONESHOT,
|
|
+ get_irq_flags(smmu, irq),
|
|
"arm-smmu-v3-priq",
|
|
smmu);
|
|
if (ret < 0)
|
|
--
|
|
2.11.0
|
|
|
|
From 929f539998cfb83834e890fd7781ddcfc327c109 Mon Sep 17 00:00:00 2001
|
|
From: Robert Richter <rrichter@cavium.com>
|
|
Date: Wed, 12 Apr 2017 10:31:15 +0200
|
|
Subject: [PATCH 34/41] iommu/arm-smmu, ACPI: Enable Cavium SMMU-v3
|
|
|
|
In next IORT spec release there will be a definition of a Cavium
|
|
specific model. Until then, enable the Cavium SMMU using cpu id
|
|
registers. Early silicon versions (A1) of Cavium's CN99xx SMMUv3
|
|
implementation must be enabled. For later silicon versions (B0) the
|
|
iort change will be in place.
|
|
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/acpi/arm64/iort.c | 13 ++++++++++++-
|
|
drivers/iommu/arm-smmu-v3.c | 19 +++++++++++++++++++
|
|
2 files changed, 31 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
|
|
index 9fd2f1d31a27..3f5f892037eb 100644
|
|
--- a/drivers/acpi/arm64/iort.c
|
|
+++ b/drivers/acpi/arm64/iort.c
|
|
@@ -26,6 +26,8 @@
|
|
#include <linux/platform_device.h>
|
|
#include <linux/slab.h>
|
|
|
|
+#include <asm/cputype.h>
|
|
+
|
|
#define IORT_TYPE_MASK(type) (1 << (type))
|
|
#define IORT_MSI_TYPE (1 << ACPI_IORT_NODE_ITS_GROUP)
|
|
#define IORT_IOMMU_TYPE ((1 << ACPI_IORT_NODE_SMMU) | \
|
|
@@ -664,6 +666,14 @@ static int __init arm_smmu_v3_count_resources(struct acpi_iort_node *node)
|
|
return num_res;
|
|
}
|
|
|
|
+static bool is_cavium_cn99xx_smmu_v3(void)
|
|
+{
|
|
+ u32 cpu_model = read_cpuid_id() & MIDR_CPU_MODEL_MASK;
|
|
+
|
|
+ return cpu_model == MIDR_CPU_MODEL(ARM_CPU_IMP_BRCM,
|
|
+ BRCM_CPU_PART_VULCAN);
|
|
+}
|
|
+
|
|
static void __init arm_smmu_v3_init_resources(struct resource *res,
|
|
struct acpi_iort_node *node)
|
|
{
|
|
@@ -678,7 +688,8 @@ static void __init arm_smmu_v3_init_resources(struct resource *res,
|
|
* Override the size, for Cavium ThunderX2 implementation
|
|
* which doesn't support the page 1 SMMU register space.
|
|
*/
|
|
- if (smmu->model == ACPI_IORT_SMMU_CAVIUM_CN99XX)
|
|
+ if (smmu->model == ACPI_IORT_SMMU_CAVIUM_CN99XX ||
|
|
+ is_cavium_cn99xx_smmu_v3())
|
|
size = SZ_64K;
|
|
|
|
res[num_res].start = smmu->base_address;
|
|
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
|
|
index 2fc067f3e199..de9774073a00 100644
|
|
--- a/drivers/iommu/arm-smmu-v3.c
|
|
+++ b/drivers/iommu/arm-smmu-v3.c
|
|
@@ -39,6 +39,8 @@
|
|
|
|
#include <linux/amba/bus.h>
|
|
|
|
+#include <asm/cputype.h>
|
|
+
|
|
#include "io-pgtable.h"
|
|
|
|
/* MMIO registers */
|
|
@@ -2640,11 +2642,28 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
|
|
}
|
|
|
|
#ifdef CONFIG_ACPI
|
|
+
|
|
+static void acpi_smmu_enable_cavium(struct arm_smmu_device *smmu)
|
|
+{
|
|
+ u32 cpu_model;
|
|
+
|
|
+ if (!IS_ENABLED(CONFIG_ARM64))
|
|
+ return;
|
|
+
|
|
+ cpu_model = read_cpuid_id() & MIDR_CPU_MODEL_MASK;
|
|
+ if (cpu_model != MIDR_CPU_MODEL(ARM_CPU_IMP_BRCM, BRCM_CPU_PART_VULCAN))
|
|
+ return;
|
|
+
|
|
+ smmu->options |= ARM_SMMU_OPT_PAGE0_REGS_ONLY;
|
|
+}
|
|
+
|
|
static void acpi_smmu_get_options(u32 model, struct arm_smmu_device *smmu)
|
|
{
|
|
if (model == ACPI_IORT_SMMU_CAVIUM_CN99XX)
|
|
smmu->options |= ARM_SMMU_OPT_PAGE0_REGS_ONLY;
|
|
|
|
+ acpi_smmu_enable_cavium(smmu);
|
|
+
|
|
dev_notice(smmu->dev, "option mask 0x%x\n", smmu->options);
|
|
}
|
|
|
|
--
|
|
2.11.0
|
|
|
|
From 8e59a6a91bf2988fb9cbc21d481f5e2b88af8140 Mon Sep 17 00:00:00 2001
|
|
From: Sunil Goutham <sgoutham@cavium.com>
|
|
Date: Fri, 5 May 2017 16:47:46 +0530
|
|
Subject: iommu/arm-smmu-v3: Increase CMDQ drain timeout value
|
|
|
|
Waiting for a CMD_SYNC to be processed involves waiting for the command
|
|
queue to drain, which can take an awful lot longer than waiting for a
|
|
single entry to become available. Consequently, the common timeout value
|
|
of 100us has been observed to be too short on some platforms when a
|
|
CMD_SYNC is issued into a queued full of TLBI commands.
|
|
|
|
This patch resolves the issue by using a different (1s) timeout when
|
|
waiting for the CMDQ to drain and using a simple back-off mechanism
|
|
when polling the cons pointer in the absence of WFE support.
|
|
|
|
Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
|
|
[will: rewrote commit message and cosmetic changes]
|
|
Signed-off-by: Will Deacon <will.deacon@arm.com>
|
|
---
|
|
drivers/iommu/arm-smmu-v3.c | 12 ++++++++++--
|
|
1 file changed, 10 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
|
|
index 380969a..6a06be7 100644
|
|
--- a/drivers/iommu/arm-smmu-v3.c
|
|
+++ b/drivers/iommu/arm-smmu-v3.c
|
|
@@ -408,6 +408,7 @@
|
|
|
|
/* High-level queue structures */
|
|
#define ARM_SMMU_POLL_TIMEOUT_US 100
|
|
+#define ARM_SMMU_CMDQ_DRAIN_TIMEOUT_US 1000000 /* 1s! */
|
|
|
|
#define MSI_IOVA_BASE 0x8000000
|
|
#define MSI_IOVA_LENGTH 0x100000
|
|
@@ -737,7 +738,13 @@ static void queue_inc_prod(struct arm_smmu_queue *q)
|
|
*/
|
|
static int queue_poll_cons(struct arm_smmu_queue *q, bool drain, bool wfe)
|
|
{
|
|
- ktime_t timeout = ktime_add_us(ktime_get(), ARM_SMMU_POLL_TIMEOUT_US);
|
|
+ ktime_t timeout;
|
|
+ unsigned int delay = 1;
|
|
+
|
|
+ /* Wait longer if it's queue drain */
|
|
+ timeout = ktime_add_us(ktime_get(), drain ?
|
|
+ ARM_SMMU_CMDQ_DRAIN_TIMEOUT_US :
|
|
+ ARM_SMMU_POLL_TIMEOUT_US);
|
|
|
|
while (queue_sync_cons(q), (drain ? !queue_empty(q) : queue_full(q))) {
|
|
if (ktime_compare(ktime_get(), timeout) > 0)
|
|
@@ -747,7 +754,8 @@ static int queue_poll_cons(struct arm_smmu_queue *q, bool drain, bool wfe)
|
|
wfe();
|
|
} else {
|
|
cpu_relax();
|
|
- udelay(1);
|
|
+ udelay(delay);
|
|
+ delay *= 2;
|
|
}
|
|
}
|
|
|
|
--
|
|
cgit v1.1
|
|
|
|
From 2e92581ecd713010e9c65ba9a90f1f7557afbe95 Mon Sep 17 00:00:00 2001
|
|
From: Manish Jaggi <mjaggi@caviumnetworks.com>
|
|
Date: Thu, 30 Mar 2017 18:47:14 -0500
|
|
Subject: [PATCH 36/41] PCI: Apply Cavium ACS quirk only to
|
|
CN81xx/CN83xx/CN88xx devices
|
|
|
|
Only apply the Cavium ACS quirk to devices with ID in the range
|
|
0xa000-0xa0ff. These are the on-chip PCI devices for CN81xx/CN83xx/CN88xx.
|
|
|
|
Fixes: b404bcfbf035 ("PCI: Add ACS quirk for all Cavium devices")
|
|
Reported-by: Alex Williamson <alex.williamson@redhat.com>
|
|
Signed-off-by: Manish Jaggi <mjaggi@cavium.com>
|
|
Acked-by: David Daney <david.daney@cavium.com>
|
|
Acked-by: Alex Williamson <alex.williamson@redhat.com>
|
|
(cherry picked from commit b77d537d00d08fcf0bf641cd3491dd7df0ad1475)
|
|
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
|
---
|
|
drivers/pci/quirks.c | 3 +++
|
|
1 file changed, 3 insertions(+)
|
|
|
|
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
|
|
index 0966a22eae13..f606916bc685 100644
|
|
--- a/drivers/pci/quirks.c
|
|
+++ b/drivers/pci/quirks.c
|
|
@@ -4133,6 +4133,9 @@ static int pci_quirk_cavium_acs(struct pci_dev *dev, u16 acs_flags)
|
|
acs_flags &= ~(PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR |
|
|
PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_DT);
|
|
|
|
+ if (!((dev->device >= 0xa000) && (dev->device <= 0xa0ff)))
|
|
+ return -ENOTTY;
|
|
+
|
|
return acs_flags ? 0 : 1;
|
|
}
|
|
|
|
--
|
|
2.11.0
|
|
|