提交 3e8f9682 编写于 作者: W Will Deacon 提交者: Cheng Jian

iommu/arm-smmu-v3: Increase maximum size of queues

mainline inclusion
from mainline-v5.3-rc1
commit d25f6ead
category: bugfix
bugzilla: 21306
CVE: NA

-------------------------------------------------------------------------

We've been artificially limiting the size of our queues to 4k so that we
don't end up allocating huge amounts of physically-contiguous memory at
probe time. However, 4k is only enough for 256 commands in the command
queue, so instead let's try to allocate the largest queue that the SMMU
supports, retrying with a smaller size if the allocation fails.

The caveat here is that we have to limit our upper bound based on
CONFIG_CMA_ALIGNMENT to ensure that our queue allocations remain
natually aligned, which is required by the SMMU architecture.
Signed-off-by: NWill Deacon <will.deacon@arm.com>
Conflicts:
	drivers/iommu/arm-smmu-v3.c
Signed-off-by: NZhen Lei <thunder.leizhen@huawei.com>
Reviewed-by: NHanjun Guo <guohanjun@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: NCheng Jian <cj.chengjian@huawei.com>
上级 190338cb
...@@ -208,6 +208,7 @@ ...@@ -208,6 +208,7 @@
#define Q_BASE_RWA (1UL << 62) #define Q_BASE_RWA (1UL << 62)
#define Q_BASE_ADDR_MASK GENMASK_ULL(51, 5) #define Q_BASE_ADDR_MASK GENMASK_ULL(51, 5)
#define Q_BASE_LOG2SIZE GENMASK(4, 0) #define Q_BASE_LOG2SIZE GENMASK(4, 0)
#define Q_MAX_SZ_SHIFT (PAGE_SHIFT + CONFIG_CMA_ALIGNMENT)
/* /*
* Stream table. * Stream table.
...@@ -272,8 +273,9 @@ ...@@ -272,8 +273,9 @@
#define STRTAB_STE_3_S2TTB_MASK GENMASK_ULL(51, 4) #define STRTAB_STE_3_S2TTB_MASK GENMASK_ULL(51, 4)
/* Command queue */ /* Command queue */
#define CMDQ_ENT_DWORDS 2 #define CMDQ_ENT_SZ_SHIFT 4
#define CMDQ_MAX_SZ_SHIFT 8 #define CMDQ_ENT_DWORDS ((1 << CMDQ_ENT_SZ_SHIFT) >> 3)
#define CMDQ_MAX_SZ_SHIFT (Q_MAX_SZ_SHIFT - CMDQ_ENT_SZ_SHIFT)
#define CMDQ_CONS_ERR GENMASK(30, 24) #define CMDQ_CONS_ERR GENMASK(30, 24)
#define CMDQ_ERR_CERROR_NONE_IDX 0 #define CMDQ_ERR_CERROR_NONE_IDX 0
...@@ -318,8 +320,9 @@ ...@@ -318,8 +320,9 @@
#define CMDQ_SYNC_1_MSIADDR_MASK GENMASK_ULL(51, 2) #define CMDQ_SYNC_1_MSIADDR_MASK GENMASK_ULL(51, 2)
/* Event queue */ /* Event queue */
#define EVTQ_ENT_DWORDS 4 #define EVTQ_ENT_SZ_SHIFT 5
#define EVTQ_MAX_SZ_SHIFT 7 #define EVTQ_ENT_DWORDS ((1 << EVTQ_ENT_SZ_SHIFT) >> 3)
#define EVTQ_MAX_SZ_SHIFT (Q_MAX_SZ_SHIFT - EVTQ_ENT_SZ_SHIFT)
#define EVTQ_0_ID GENMASK_ULL(7, 0) #define EVTQ_0_ID GENMASK_ULL(7, 0)
#define EVT_ID_TRANSLATION_FAULT 0x10 #define EVT_ID_TRANSLATION_FAULT 0x10
...@@ -342,8 +345,9 @@ ...@@ -342,8 +345,9 @@
#define EVTQ_3_IPA GENMASK_ULL(51, 12) #define EVTQ_3_IPA GENMASK_ULL(51, 12)
/* PRI queue */ /* PRI queue */
#define PRIQ_ENT_DWORDS 2 #define PRIQ_ENT_SZ_SHIFT 4
#define PRIQ_MAX_SZ_SHIFT 8 #define PRIQ_ENT_DWORDS ((1 << PRIQ_ENT_SZ_SHIFT) >> 3)
#define PRIQ_MAX_SZ_SHIFT (Q_MAX_SZ_SHIFT - PRIQ_ENT_SZ_SHIFT)
#define PRIQ_0_SID GENMASK_ULL(31, 0) #define PRIQ_0_SID GENMASK_ULL(31, 0)
#define PRIQ_0_SSID GENMASK_ULL(51, 32) #define PRIQ_0_SSID GENMASK_ULL(51, 32)
...@@ -888,7 +892,7 @@ static int queue_remove_raw(struct arm_smmu_queue *q, u64 *ent) ...@@ -888,7 +892,7 @@ static int queue_remove_raw(struct arm_smmu_queue *q, u64 *ent)
/* High-level queue accessors */ /* High-level queue accessors */
static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent) static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent)
{ {
memset(cmd, 0, CMDQ_ENT_DWORDS << 3); memset(cmd, 0, 1 << CMDQ_ENT_SZ_SHIFT);
cmd[0] |= FIELD_PREP(CMDQ_0_OP, ent->opcode); cmd[0] |= FIELD_PREP(CMDQ_0_OP, ent->opcode);
switch (ent->opcode) { switch (ent->opcode) {
...@@ -2736,17 +2740,32 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu, ...@@ -2736,17 +2740,32 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
struct arm_smmu_queue *q, struct arm_smmu_queue *q,
unsigned long prod_off, unsigned long prod_off,
unsigned long cons_off, unsigned long cons_off,
size_t dwords) size_t dwords, const char *name)
{ {
size_t qsz = ((1 << q->max_n_shift) * dwords) << 3; size_t qsz;
do {
qsz = ((1 << q->max_n_shift) * dwords) << 3;
q->base = dmam_alloc_coherent(smmu->dev, qsz, &q->base_dma,
GFP_KERNEL);
if (q->base || qsz < PAGE_SIZE)
break;
q->max_n_shift--;
} while (1);
q->base = dmam_alloc_coherent(smmu->dev, qsz, &q->base_dma, GFP_KERNEL);
if (!q->base) { if (!q->base) {
dev_err(smmu->dev, "failed to allocate queue (0x%zx bytes)\n", dev_err(smmu->dev,
qsz); "failed to allocate queue (0x%zx bytes) for %s\n",
qsz, name);
return -ENOMEM; return -ENOMEM;
} }
if (!WARN_ON(q->base_dma & (qsz - 1))) {
dev_info(smmu->dev, "allocated %u entries for %s\n",
1 << q->max_n_shift, name);
}
q->prod_reg = arm_smmu_page1_fixup(prod_off, smmu); q->prod_reg = arm_smmu_page1_fixup(prod_off, smmu);
q->cons_reg = arm_smmu_page1_fixup(cons_off, smmu); q->cons_reg = arm_smmu_page1_fixup(cons_off, smmu);
q->ent_dwords = dwords; q->ent_dwords = dwords;
...@@ -2770,13 +2789,15 @@ static int arm_smmu_init_queues(struct arm_smmu_device *smmu) ...@@ -2770,13 +2789,15 @@ static int arm_smmu_init_queues(struct arm_smmu_device *smmu)
/* cmdq */ /* cmdq */
spin_lock_init(&smmu->cmdq.lock); spin_lock_init(&smmu->cmdq.lock);
ret = arm_smmu_init_one_queue(smmu, &smmu->cmdq.q, ARM_SMMU_CMDQ_PROD, ret = arm_smmu_init_one_queue(smmu, &smmu->cmdq.q, ARM_SMMU_CMDQ_PROD,
ARM_SMMU_CMDQ_CONS, CMDQ_ENT_DWORDS); ARM_SMMU_CMDQ_CONS, CMDQ_ENT_DWORDS,
"cmdq");
if (ret) if (ret)
return ret; return ret;
/* evtq */ /* evtq */
ret = arm_smmu_init_one_queue(smmu, &smmu->evtq.q, ARM_SMMU_EVTQ_PROD, ret = arm_smmu_init_one_queue(smmu, &smmu->evtq.q, ARM_SMMU_EVTQ_PROD,
ARM_SMMU_EVTQ_CONS, EVTQ_ENT_DWORDS); ARM_SMMU_EVTQ_CONS, EVTQ_ENT_DWORDS,
"evtq");
if (ret) if (ret)
return ret; return ret;
...@@ -2785,7 +2806,8 @@ static int arm_smmu_init_queues(struct arm_smmu_device *smmu) ...@@ -2785,7 +2806,8 @@ static int arm_smmu_init_queues(struct arm_smmu_device *smmu)
return 0; return 0;
return arm_smmu_init_one_queue(smmu, &smmu->priq.q, ARM_SMMU_PRIQ_PROD, return arm_smmu_init_one_queue(smmu, &smmu->priq.q, ARM_SMMU_PRIQ_PROD,
ARM_SMMU_PRIQ_CONS, PRIQ_ENT_DWORDS); ARM_SMMU_PRIQ_CONS, PRIQ_ENT_DWORDS,
"priq");
} }
static int arm_smmu_init_l1_strtab(struct arm_smmu_device *smmu) static int arm_smmu_init_l1_strtab(struct arm_smmu_device *smmu)
...@@ -3532,7 +3554,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) ...@@ -3532,7 +3554,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
return -ENXIO; return -ENXIO;
} }
/* Queue sizes, capped at 4k */ /* Queue sizes, capped to ensure natural alignment */
smmu->cmdq.q.max_n_shift = min_t(u32, CMDQ_MAX_SZ_SHIFT, smmu->cmdq.q.max_n_shift = min_t(u32, CMDQ_MAX_SZ_SHIFT,
FIELD_GET(IDR1_CMDQS, reg)); FIELD_GET(IDR1_CMDQS, reg));
if (!smmu->cmdq.q.max_n_shift) { if (!smmu->cmdq.q.max_n_shift) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册