aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhen Lei <thunder.leizhen@huawei.com>2015-07-06 23:30:18 -0400
committerWill Deacon <will.deacon@arm.com>2015-07-08 12:24:39 -0400
commit5e92946c39ca6abc65e34775a93cc1d1a819c0e3 (patch)
treee55bc9345eaef4358aa963e510a4dbe3500d8023
parente2f4c2330f08ba73d9a3c919a3d6ca33dce7d2c2 (diff)
iommu/arm-smmu: Skip the execution of CMD_PREFETCH_CONFIG
Hisilicon SMMUv3 devices treat CMD_PREFETCH_CONFIG as a illegal command, execute it will trigger GERROR interrupt. Although the gerror code manage to turn the prefetch into a SYNC, and the system can continue to run normally, but it's ugly to print error information. Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com> [will: extended binding documentation] Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt3
-rw-r--r--drivers/iommu/arm-smmu-v3.c32
2 files changed, 34 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
index c03eec116872..3443e0f838df 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
@@ -35,3 +35,6 @@ the PCIe specification.
35 35
36 NOTE: this only applies to the SMMU itself, not 36 NOTE: this only applies to the SMMU itself, not
37 masters connected upstream of the SMMU. 37 masters connected upstream of the SMMU.
38
39- hisilicon,broken-prefetch-cmd
40 : Avoid sending CMD_PREFETCH_* commands to the SMMU.
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 29cba3280af7..da902baaa794 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -543,6 +543,9 @@ struct arm_smmu_device {
543#define ARM_SMMU_FEAT_HYP (1 << 12) 543#define ARM_SMMU_FEAT_HYP (1 << 12)
544 u32 features; 544 u32 features;
545 545
546#define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0)
547 u32 options;
548
546 struct arm_smmu_cmdq cmdq; 549 struct arm_smmu_cmdq cmdq;
547 struct arm_smmu_evtq evtq; 550 struct arm_smmu_evtq evtq;
548 struct arm_smmu_priq priq; 551 struct arm_smmu_priq priq;
@@ -603,11 +606,35 @@ struct arm_smmu_domain {
603static DEFINE_SPINLOCK(arm_smmu_devices_lock); 606static DEFINE_SPINLOCK(arm_smmu_devices_lock);
604static LIST_HEAD(arm_smmu_devices); 607static LIST_HEAD(arm_smmu_devices);
605 608
609struct arm_smmu_option_prop {
610 u32 opt;
611 const char *prop;
612};
613
614static struct arm_smmu_option_prop arm_smmu_options[] = {
615 { ARM_SMMU_OPT_SKIP_PREFETCH, "hisilicon,broken-prefetch-cmd" },
616 { 0, NULL},
617};
618
606static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom) 619static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
607{ 620{
608 return container_of(dom, struct arm_smmu_domain, domain); 621 return container_of(dom, struct arm_smmu_domain, domain);
609} 622}
610 623
624static void parse_driver_options(struct arm_smmu_device *smmu)
625{
626 int i = 0;
627
628 do {
629 if (of_property_read_bool(smmu->dev->of_node,
630 arm_smmu_options[i].prop)) {
631 smmu->options |= arm_smmu_options[i].opt;
632 dev_notice(smmu->dev, "option %s\n",
633 arm_smmu_options[i].prop);
634 }
635 } while (arm_smmu_options[++i].opt);
636}
637
611/* Low-level queue manipulation functions */ 638/* Low-level queue manipulation functions */
612static bool queue_full(struct arm_smmu_queue *q) 639static bool queue_full(struct arm_smmu_queue *q)
613{ 640{
@@ -1037,7 +1064,8 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid,
1037 arm_smmu_sync_ste_for_sid(smmu, sid); 1064 arm_smmu_sync_ste_for_sid(smmu, sid);
1038 1065
1039 /* It's likely that we'll want to use the new STE soon */ 1066 /* It's likely that we'll want to use the new STE soon */
1040 arm_smmu_cmdq_issue_cmd(smmu, &prefetch_cmd); 1067 if (!(smmu->options & ARM_SMMU_OPT_SKIP_PREFETCH))
1068 arm_smmu_cmdq_issue_cmd(smmu, &prefetch_cmd);
1041} 1069}
1042 1070
1043static void arm_smmu_init_bypass_stes(u64 *strtab, unsigned int nent) 1071static void arm_smmu_init_bypass_stes(u64 *strtab, unsigned int nent)
@@ -2575,6 +2603,8 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
2575 if (irq > 0) 2603 if (irq > 0)
2576 smmu->gerr_irq = irq; 2604 smmu->gerr_irq = irq;
2577 2605
2606 parse_driver_options(smmu);
2607
2578 /* Probe the h/w */ 2608 /* Probe the h/w */
2579 ret = arm_smmu_device_probe(smmu); 2609 ret = arm_smmu_device_probe(smmu);
2580 if (ret) 2610 if (ret)