From patchwork Sat Sep 5 20:04:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 11759319 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C2C52618 for ; Sat, 5 Sep 2020 20:04:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9C1A020760 for ; Sat, 5 Sep 2020 20:04:55 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="lTKPgGHM" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728786AbgIEUEy (ORCPT ); Sat, 5 Sep 2020 16:04:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49732 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728828AbgIEUEw (ORCPT ); Sat, 5 Sep 2020 16:04:52 -0400 Received: from mail-pj1-x1041.google.com (mail-pj1-x1041.google.com [IPv6:2607:f8b0:4864:20::1041]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AAFB0C061244; Sat, 5 Sep 2020 13:04:51 -0700 (PDT) Received: by mail-pj1-x1041.google.com with SMTP id gf14so4566614pjb.5; Sat, 05 Sep 2020 13:04:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=PAP++uQEfbrfeWkc7acc7DA5Qvr9EoHHyqUH0VD3He8=; b=lTKPgGHM4pGLFeVWDGXYCUbuie5QBl0D0r4wJvrzKdzx1t7F0ZQTjTPyR07Pg6h90J mRTG6eGN2piNIWVCYISt4OcEX42TuSU3XI72eM2ZW0qtjp0e/Ovrt3Wu47yMb2MekWn5 fd7VGwgOIBDpgxU/4Dv93xFAgj/l/HdzsoMVJk8M6vT3JQQa4RqfULHX/AWV/fpgwy2f 2QAtdCENab5Xdcvd7L2BwisTAJZcEwNvJOdjebp9oNrCatQQX1r5OOTZTvbf5g+T8h4O eFGViWWaLShbHH8fMlFM4VWYIXi2gCQV2i0TtzA484xVsYiSDSKTlf2/Lyv7rqEQkNxn pcCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=PAP++uQEfbrfeWkc7acc7DA5Qvr9EoHHyqUH0VD3He8=; b=E1vgVaU7ujjpeKDDPGbewMauBuAU5DNEHzXnRcLsvSFe9n8ydcYX7MDJFBhnl5WNaC Fzv43aJeiO4+SjbH6HDCRG+3pe9qeFh2TmgyeWKk52rcFHH5fGlemXvls0Xk2opdffQh V2W+m1EUb/Uf4FUZ70qnAWSYGm74tN38E2xo9w0uISJMzpoz7Z6rjS5yYuQm4dIqGT9I 9N3HGaOque6NifIUz3b4ILHmBhXX2sYOKmPLMmxVmYGVmbxzy/vB5jk7gXosChA5lRAQ U6C69F88JajNP/TOB0yGti+uhX2XvnlC4jiFG8w0G47D7Yh31Z2fups7s/qZmmDMCUU/ m6Vw== X-Gm-Message-State: AOAM530Bcq40HJUv4XwW+86PbG7CqJfGzq6PvxQ4Rtf6BwaWI+rNNRaP h1ISkAx6W3gI+TeW57MBipo= X-Google-Smtp-Source: ABdhPJycwwCLdWKq9ZKmLOfe22QCU1nLv2XzaQeZYPu3DeWjAfY2F1/8Q0WdLNAyBbKC6CG85iYkLA== X-Received: by 2002:a17:902:8a85:: with SMTP id p5mr13570330plo.193.1599336291107; Sat, 05 Sep 2020 13:04:51 -0700 (PDT) Received: from localhost (c-73-25-156-94.hsd1.or.comcast.net. [73.25.156.94]) by smtp.gmail.com with ESMTPSA id n67sm8287988pgn.14.2020.09.05.13.04.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 05 Sep 2020 13:04:50 -0700 (PDT) From: Rob Clark To: iommu@lists.linux-foundation.org, dri-devel@lists.freedesktop.org, Will Deacon , Robin Murphy , Joerg Roedel Cc: linux-arm-msm@vger.kernel.org, freedreno@lists.freedesktop.org, Bjorn Andersson , Sibi Sankar , Vivek Gautam , Stephen Boyd , Akhil P Oommen , Jordan Crouse , Rob Clark , Jonathan Marek , Hanna Hawa , Greg Kroah-Hartman , Krishna Reddy , linux-arm-kernel@lists.infradead.org (moderated list:ARM SMMU DRIVERS), linux-kernel@vger.kernel.org (open list) Subject: [PATCH v17 14/20] iommu/arm-smmu: Prepare for the adreno-smmu implementation Date: Sat, 5 Sep 2020 13:04:20 -0700 Message-Id: <20200905200454.240929-15-robdclark@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200905200454.240929-1-robdclark@gmail.com> References: <20200905200454.240929-1-robdclark@gmail.com> MIME-Version: 1.0 Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org From: Jordan Crouse Do a bit of prep work to add the upcoming adreno-smmu implementation. Add an hook to allow the implementation to choose which context banks to allocate. Move some of the common structs to arm-smmu.h in anticipation of them being used by the implementations and update some of the existing hooks to pass more information that the implementation will need. These modifications will be used by the upcoming Adreno SMMU implementation to identify the GPU device and properly configure it for pagetable switching. Co-developed-by: Rob Clark Signed-off-by: Jordan Crouse Signed-off-by: Rob Clark Reviewed-by: Bjorn Andersson --- drivers/iommu/arm/arm-smmu/arm-smmu-impl.c | 2 +- drivers/iommu/arm/arm-smmu/arm-smmu.c | 74 ++++++---------------- drivers/iommu/arm/arm-smmu/arm-smmu.h | 52 ++++++++++++++- 3 files changed, 73 insertions(+), 55 deletions(-) diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c index a9861dcd0884..88f17cc33023 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c @@ -69,7 +69,7 @@ static int cavium_cfg_probe(struct arm_smmu_device *smmu) } static int cavium_init_context(struct arm_smmu_domain *smmu_domain, - struct io_pgtable_cfg *pgtbl_cfg) + struct io_pgtable_cfg *pgtbl_cfg, struct device *dev) { struct cavium_smmu *cs = container_of(smmu_domain->smmu, struct cavium_smmu, smmu); diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c index 8e884e58f208..dad7fa86fbd4 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c @@ -65,41 +65,10 @@ module_param(disable_bypass, bool, S_IRUGO); MODULE_PARM_DESC(disable_bypass, "Disable bypass streams such that incoming transactions from devices that are not attached to an iommu domain will report an abort back to the device and will not be allowed to pass through the SMMU."); -struct arm_smmu_s2cr { - struct iommu_group *group; - int count; - enum arm_smmu_s2cr_type type; - enum arm_smmu_s2cr_privcfg privcfg; - u8 cbndx; -}; - #define s2cr_init_val (struct arm_smmu_s2cr){ \ .type = disable_bypass ? S2CR_TYPE_FAULT : S2CR_TYPE_BYPASS, \ } -struct arm_smmu_smr { - u16 mask; - u16 id; - bool valid; -}; - -struct arm_smmu_cb { - u64 ttbr[2]; - u32 tcr[2]; - u32 mair[2]; - struct arm_smmu_cfg *cfg; -}; - -struct arm_smmu_master_cfg { - struct arm_smmu_device *smmu; - s16 smendx[]; -}; -#define INVALID_SMENDX -1 -#define cfg_smendx(cfg, fw, i) \ - (i >= fw->num_ids ? INVALID_SMENDX : cfg->smendx[i]) -#define for_each_cfg_sme(cfg, fw, i, idx) \ - for (i = 0; idx = cfg_smendx(cfg, fw, i), i < fw->num_ids; ++i) - static bool using_legacy_binding, using_generic_binding; static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu) @@ -234,19 +203,6 @@ static int arm_smmu_register_legacy_master(struct device *dev, } #endif /* CONFIG_ARM_SMMU_LEGACY_DT_BINDINGS */ -static int __arm_smmu_alloc_bitmap(unsigned long *map, int start, int end) -{ - int idx; - - do { - idx = find_next_zero_bit(map, end, start); - if (idx == end) - return -ENOSPC; - } while (test_and_set_bit(idx, map)); - - return idx; -} - static void __arm_smmu_free_bitmap(unsigned long *map, int idx) { clear_bit(idx, map); @@ -578,7 +534,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, } } -static void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx) +void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx) { u32 reg; bool stage1; @@ -664,8 +620,19 @@ static void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx) arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_SCTLR, reg); } +static int arm_smmu_alloc_context_bank(struct arm_smmu_domain *smmu_domain, + struct arm_smmu_device *smmu, + struct device *dev, unsigned int start) +{ + if (smmu->impl && smmu->impl->alloc_context_bank) + return smmu->impl->alloc_context_bank(smmu_domain, smmu, dev, start); + + return __arm_smmu_alloc_bitmap(smmu->context_map, start, smmu->num_context_banks); +} + static int arm_smmu_init_domain_context(struct iommu_domain *domain, - struct arm_smmu_device *smmu) + struct arm_smmu_device *smmu, + struct device *dev) { int irq, start, ret = 0; unsigned long ias, oas; @@ -780,10 +747,13 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, ret = -EINVAL; goto out_unlock; } - ret = __arm_smmu_alloc_bitmap(smmu->context_map, start, - smmu->num_context_banks); - if (ret < 0) + + ret = arm_smmu_alloc_context_bank(smmu_domain, smmu, dev, start); + if (ret < 0) { goto out_unlock; + } + + smmu_domain->smmu = smmu; cfg->cbndx = ret; if (smmu->version < ARM_SMMU_V2) { @@ -798,8 +768,6 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, else cfg->asid = cfg->cbndx; - smmu_domain->smmu = smmu; - pgtbl_cfg = (struct io_pgtable_cfg) { .pgsize_bitmap = smmu->pgsize_bitmap, .ias = ias, @@ -810,7 +778,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, }; if (smmu->impl && smmu->impl->init_context) { - ret = smmu->impl->init_context(smmu_domain, &pgtbl_cfg); + ret = smmu->impl->init_context(smmu_domain, &pgtbl_cfg, dev); if (ret) goto out_clear_smmu; } @@ -1194,7 +1162,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return ret; /* Ensure that the domain is finalised */ - ret = arm_smmu_init_domain_context(domain, smmu); + ret = arm_smmu_init_domain_context(domain, smmu, dev); if (ret < 0) goto rpm_put; diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h index f3e456893f28..9aaacc906597 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h @@ -256,6 +256,21 @@ enum arm_smmu_implementation { QCOM_SMMUV2, }; +struct arm_smmu_s2cr { + struct iommu_group *group; + int count; + enum arm_smmu_s2cr_type type; + enum arm_smmu_s2cr_privcfg privcfg; + u8 cbndx; +}; + +struct arm_smmu_smr { + u16 mask; + u16 id; + bool valid; + bool pinned; +}; + struct arm_smmu_device { struct device *dev; @@ -331,6 +346,13 @@ struct arm_smmu_cfg { }; #define ARM_SMMU_INVALID_IRPTNDX 0xff +struct arm_smmu_cb { + u64 ttbr[2]; + u32 tcr[2]; + u32 mair[2]; + struct arm_smmu_cfg *cfg; +}; + enum arm_smmu_domain_stage { ARM_SMMU_DOMAIN_S1 = 0, ARM_SMMU_DOMAIN_S2, @@ -350,6 +372,11 @@ struct arm_smmu_domain { struct iommu_domain domain; }; +struct arm_smmu_master_cfg { + struct arm_smmu_device *smmu; + s16 smendx[]; +}; + static inline u32 arm_smmu_lpae_tcr(struct io_pgtable_cfg *cfg) { u32 tcr = FIELD_PREP(ARM_SMMU_TCR_TG0, cfg->arm_lpae_s1_cfg.tcr.tg) | @@ -400,14 +427,36 @@ struct arm_smmu_impl { int (*cfg_probe)(struct arm_smmu_device *smmu); int (*reset)(struct arm_smmu_device *smmu); int (*init_context)(struct arm_smmu_domain *smmu_domain, - struct io_pgtable_cfg *cfg); + struct io_pgtable_cfg *cfg, struct device *dev); void (*tlb_sync)(struct arm_smmu_device *smmu, int page, int sync, int status); int (*def_domain_type)(struct device *dev); irqreturn_t (*global_fault)(int irq, void *dev); irqreturn_t (*context_fault)(int irq, void *dev); + int (*alloc_context_bank)(struct arm_smmu_domain *smmu_domain, + struct arm_smmu_device *smmu, + struct device *dev, int start); }; +#define INVALID_SMENDX -1 +#define cfg_smendx(cfg, fw, i) \ + (i >= fw->num_ids ? INVALID_SMENDX : cfg->smendx[i]) +#define for_each_cfg_sme(cfg, fw, i, idx) \ + for (i = 0; idx = cfg_smendx(cfg, fw, i), i < fw->num_ids; ++i) + +static inline int __arm_smmu_alloc_bitmap(unsigned long *map, int start, int end) +{ + int idx; + + do { + idx = find_next_zero_bit(map, end, start); + if (idx == end) + return -ENOSPC; + } while (test_and_set_bit(idx, map)); + + return idx; +} + static inline void __iomem *arm_smmu_page(struct arm_smmu_device *smmu, int n) { return smmu->base + (n << smmu->pgshift); @@ -472,6 +521,7 @@ struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu); struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu); struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu); +void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx); int arm_mmu500_reset(struct arm_smmu_device *smmu); #endif /* _ARM_SMMU_H */