Skip to content

Commit d81dc82

Browse files
committed
Merge branch 'for-joerg/arm-smmu/updates' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into arm/smmu
2 parents d72e90f + b63b343 commit d81dc82

File tree

4 files changed

+36
-15
lines changed

4 files changed

+36
-15
lines changed

drivers/iommu/arm-smmu-v3.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <linux/acpi_iort.h>
2525
#include <linux/bitfield.h>
2626
#include <linux/bitops.h>
27+
#include <linux/crash_dump.h>
2728
#include <linux/delay.h>
2829
#include <linux/dma-iommu.h>
2930
#include <linux/err.h>
@@ -366,7 +367,7 @@
366367
#define MSI_IOVA_BASE 0x8000000
367368
#define MSI_IOVA_LENGTH 0x100000
368369

369-
static bool disable_bypass;
370+
static bool disable_bypass = 1;
370371
module_param_named(disable_bypass, disable_bypass, bool, S_IRUGO);
371372
MODULE_PARM_DESC(disable_bypass,
372373
"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.");
@@ -1301,6 +1302,7 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev)
13011302

13021303
/* Sync our overflow flag, as we believe we're up to speed */
13031304
q->cons = Q_OVF(q, q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons);
1305+
writel(q->cons, q->cons_reg);
13041306
return IRQ_HANDLED;
13051307
}
13061308

@@ -2211,8 +2213,12 @@ static int arm_smmu_update_gbpa(struct arm_smmu_device *smmu, u32 set, u32 clr)
22112213
reg &= ~clr;
22122214
reg |= set;
22132215
writel_relaxed(reg | GBPA_UPDATE, gbpa);
2214-
return readl_relaxed_poll_timeout(gbpa, reg, !(reg & GBPA_UPDATE),
2215-
1, ARM_SMMU_POLL_TIMEOUT_US);
2216+
ret = readl_relaxed_poll_timeout(gbpa, reg, !(reg & GBPA_UPDATE),
2217+
1, ARM_SMMU_POLL_TIMEOUT_US);
2218+
2219+
if (ret)
2220+
dev_err(smmu->dev, "GBPA not responding to update\n");
2221+
return ret;
22162222
}
22172223

22182224
static void arm_smmu_free_msis(void *data)
@@ -2392,8 +2398,15 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
23922398

23932399
/* Clear CR0 and sync (disables SMMU and queue processing) */
23942400
reg = readl_relaxed(smmu->base + ARM_SMMU_CR0);
2395-
if (reg & CR0_SMMUEN)
2401+
if (reg & CR0_SMMUEN) {
2402+
if (is_kdump_kernel()) {
2403+
arm_smmu_update_gbpa(smmu, GBPA_ABORT, 0);
2404+
arm_smmu_device_disable(smmu);
2405+
return -EBUSY;
2406+
}
2407+
23962408
dev_warn(smmu->dev, "SMMU currently enabled! Resetting...\n");
2409+
}
23972410

23982411
ret = arm_smmu_device_disable(smmu);
23992412
if (ret)
@@ -2491,10 +2504,8 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
24912504
enables |= CR0_SMMUEN;
24922505
} else {
24932506
ret = arm_smmu_update_gbpa(smmu, 0, GBPA_ABORT);
2494-
if (ret) {
2495-
dev_err(smmu->dev, "GBPA not responding to update\n");
2507+
if (ret)
24962508
return ret;
2497-
}
24982509
}
24992510
ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
25002511
ARM_SMMU_CR0ACK);

drivers/iommu/arm-smmu.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2103,12 +2103,16 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
21032103
if (err)
21042104
return err;
21052105

2106-
if (smmu->version == ARM_SMMU_V2 &&
2107-
smmu->num_context_banks != smmu->num_context_irqs) {
2108-
dev_err(dev,
2109-
"found only %d context interrupt(s) but %d required\n",
2110-
smmu->num_context_irqs, smmu->num_context_banks);
2111-
return -ENODEV;
2106+
if (smmu->version == ARM_SMMU_V2) {
2107+
if (smmu->num_context_banks > smmu->num_context_irqs) {
2108+
dev_err(dev,
2109+
"found only %d context irq(s) but %d required\n",
2110+
smmu->num_context_irqs, smmu->num_context_banks);
2111+
return -ENODEV;
2112+
}
2113+
2114+
/* Ignore superfluous interrupts */
2115+
smmu->num_context_irqs = smmu->num_context_banks;
21122116
}
21132117

21142118
for (i = 0; i < smmu->num_global_irqs; ++i) {

drivers/iommu/io-pgtable-arm-v7s.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
192192
{
193193
struct io_pgtable_cfg *cfg = &data->iop.cfg;
194194
struct device *dev = cfg->iommu_dev;
195+
phys_addr_t phys;
195196
dma_addr_t dma;
196197
size_t size = ARM_V7S_TABLE_SIZE(lvl);
197198
void *table = NULL;
@@ -200,6 +201,10 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
200201
table = (void *)__get_dma_pages(__GFP_ZERO, get_order(size));
201202
else if (lvl == 2)
202203
table = kmem_cache_zalloc(data->l2_tables, gfp | GFP_DMA);
204+
phys = virt_to_phys(table);
205+
if (phys != (arm_v7s_iopte)phys)
206+
/* Doesn't fit in PTE */
207+
goto out_free;
203208
if (table && !(cfg->quirks & IO_PGTABLE_QUIRK_NO_DMA)) {
204209
dma = dma_map_single(dev, table, size, DMA_TO_DEVICE);
205210
if (dma_mapping_error(dev, dma))
@@ -209,7 +214,7 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
209214
* address directly, so if the DMA layer suggests otherwise by
210215
* translating or truncating them, that bodes very badly...
211216
*/
212-
if (dma != virt_to_phys(table))
217+
if (dma != phys)
213218
goto out_unmap;
214219
}
215220
kmemleak_ignore(table);

drivers/iommu/io-pgtable-arm.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
237237
void *pages;
238238

239239
VM_BUG_ON((gfp & __GFP_HIGHMEM));
240-
p = alloc_pages_node(dev_to_node(dev), gfp | __GFP_ZERO, order);
240+
p = alloc_pages_node(dev ? dev_to_node(dev) : NUMA_NO_NODE,
241+
gfp | __GFP_ZERO, order);
241242
if (!p)
242243
return NULL;
243244

0 commit comments

Comments
 (0)