summaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorMagnus Damm <damm+renesas@opensource.se>2017-10-16 08:30:18 -0400
committerAlex Williamson <alex.williamson@redhat.com>2017-11-06 12:29:39 -0500
commitd574893aee991efa67fefa849347c49de5df8108 (patch)
treea3f7280771139668021b51b0c6a18f67dfb5671a /drivers/iommu
parent1c894225bf5b1cdffac0c6ef935b61273203d7d5 (diff)
iommu/ipmmu-vmsa: Write IMCTR twice
Write IMCTR both in the root device and the leaf node. To allow access of IMCTR introduce the following function: - ipmmu_ctx_write_all() While at it also rename context functions: - ipmmu_ctx_read() -> ipmmu_ctx_read_root() - ipmmu_ctx_write() -> ipmmu_ctx_write_root() Signed-off-by: Magnus Damm <damm+renesas@opensource.se> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/ipmmu-vmsa.c56
1 files changed, 35 insertions, 21 deletions
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index 6b74ec62f4b4..7587017972b0 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -248,19 +248,31 @@ static void ipmmu_write(struct ipmmu_vmsa_device *mmu, unsigned int offset,
248 iowrite32(data, mmu->base + offset); 248 iowrite32(data, mmu->base + offset);
249} 249}
250 250
251static u32 ipmmu_ctx_read(struct ipmmu_vmsa_domain *domain, unsigned int reg) 251static u32 ipmmu_ctx_read_root(struct ipmmu_vmsa_domain *domain,
252 unsigned int reg)
252{ 253{
253 return ipmmu_read(domain->mmu->root, 254 return ipmmu_read(domain->mmu->root,
254 domain->context_id * IM_CTX_SIZE + reg); 255 domain->context_id * IM_CTX_SIZE + reg);
255} 256}
256 257
257static void ipmmu_ctx_write(struct ipmmu_vmsa_domain *domain, unsigned int reg, 258static void ipmmu_ctx_write_root(struct ipmmu_vmsa_domain *domain,
258 u32 data) 259 unsigned int reg, u32 data)
259{ 260{
260 ipmmu_write(domain->mmu->root, 261 ipmmu_write(domain->mmu->root,
261 domain->context_id * IM_CTX_SIZE + reg, data); 262 domain->context_id * IM_CTX_SIZE + reg, data);
262} 263}
263 264
265static void ipmmu_ctx_write_all(struct ipmmu_vmsa_domain *domain,
266 unsigned int reg, u32 data)
267{
268 if (domain->mmu != domain->mmu->root)
269 ipmmu_write(domain->mmu,
270 domain->context_id * IM_CTX_SIZE + reg, data);
271
272 ipmmu_write(domain->mmu->root,
273 domain->context_id * IM_CTX_SIZE + reg, data);
274}
275
264/* ----------------------------------------------------------------------------- 276/* -----------------------------------------------------------------------------
265 * TLB and microTLB Management 277 * TLB and microTLB Management
266 */ 278 */
@@ -270,7 +282,7 @@ static void ipmmu_tlb_sync(struct ipmmu_vmsa_domain *domain)
270{ 282{
271 unsigned int count = 0; 283 unsigned int count = 0;
272 284
273 while (ipmmu_ctx_read(domain, IMCTR) & IMCTR_FLUSH) { 285 while (ipmmu_ctx_read_root(domain, IMCTR) & IMCTR_FLUSH) {
274 cpu_relax(); 286 cpu_relax();
275 if (++count == TLB_LOOP_TIMEOUT) { 287 if (++count == TLB_LOOP_TIMEOUT) {
276 dev_err_ratelimited(domain->mmu->dev, 288 dev_err_ratelimited(domain->mmu->dev,
@@ -285,9 +297,9 @@ static void ipmmu_tlb_invalidate(struct ipmmu_vmsa_domain *domain)
285{ 297{
286 u32 reg; 298 u32 reg;
287 299
288 reg = ipmmu_ctx_read(domain, IMCTR); 300 reg = ipmmu_ctx_read_root(domain, IMCTR);
289 reg |= IMCTR_FLUSH; 301 reg |= IMCTR_FLUSH;
290 ipmmu_ctx_write(domain, IMCTR, reg); 302 ipmmu_ctx_write_all(domain, IMCTR, reg);
291 303
292 ipmmu_tlb_sync(domain); 304 ipmmu_tlb_sync(domain);
293} 305}
@@ -428,31 +440,32 @@ static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
428 440
429 /* TTBR0 */ 441 /* TTBR0 */
430 ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0]; 442 ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0];
431 ipmmu_ctx_write(domain, IMTTLBR0, ttbr); 443 ipmmu_ctx_write_root(domain, IMTTLBR0, ttbr);
432 ipmmu_ctx_write(domain, IMTTUBR0, ttbr >> 32); 444 ipmmu_ctx_write_root(domain, IMTTUBR0, ttbr >> 32);
433 445
434 /* 446 /*
435 * TTBCR 447 * TTBCR
436 * We use long descriptors with inner-shareable WBWA tables and allocate 448 * We use long descriptors with inner-shareable WBWA tables and allocate
437 * the whole 32-bit VA space to TTBR0. 449 * the whole 32-bit VA space to TTBR0.
438 */ 450 */
439 ipmmu_ctx_write(domain, IMTTBCR, IMTTBCR_EAE | 451 ipmmu_ctx_write_root(domain, IMTTBCR, IMTTBCR_EAE |
440 IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA | 452 IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
441 IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1); 453 IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
442 454
443 /* MAIR0 */ 455 /* MAIR0 */
444 ipmmu_ctx_write(domain, IMMAIR0, domain->cfg.arm_lpae_s1_cfg.mair[0]); 456 ipmmu_ctx_write_root(domain, IMMAIR0,
457 domain->cfg.arm_lpae_s1_cfg.mair[0]);
445 458
446 /* IMBUSCR */ 459 /* IMBUSCR */
447 ipmmu_ctx_write(domain, IMBUSCR, 460 ipmmu_ctx_write_root(domain, IMBUSCR,
448 ipmmu_ctx_read(domain, IMBUSCR) & 461 ipmmu_ctx_read_root(domain, IMBUSCR) &
449 ~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK)); 462 ~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
450 463
451 /* 464 /*
452 * IMSTR 465 * IMSTR
453 * Clear all interrupt flags. 466 * Clear all interrupt flags.
454 */ 467 */
455 ipmmu_ctx_write(domain, IMSTR, ipmmu_ctx_read(domain, IMSTR)); 468 ipmmu_ctx_write_root(domain, IMSTR, ipmmu_ctx_read_root(domain, IMSTR));
456 469
457 /* 470 /*
458 * IMCTR 471 * IMCTR
@@ -461,7 +474,8 @@ static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
461 * software management as we have no use for it. Flush the TLB as 474 * software management as we have no use for it. Flush the TLB as
462 * required when modifying the context registers. 475 * required when modifying the context registers.
463 */ 476 */
464 ipmmu_ctx_write(domain, IMCTR, IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN); 477 ipmmu_ctx_write_all(domain, IMCTR,
478 IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
465 479
466 return 0; 480 return 0;
467} 481}
@@ -474,7 +488,7 @@ static void ipmmu_domain_destroy_context(struct ipmmu_vmsa_domain *domain)
474 * 488 *
475 * TODO: Is TLB flush really needed ? 489 * TODO: Is TLB flush really needed ?
476 */ 490 */
477 ipmmu_ctx_write(domain, IMCTR, IMCTR_FLUSH); 491 ipmmu_ctx_write_all(domain, IMCTR, IMCTR_FLUSH);
478 ipmmu_tlb_sync(domain); 492 ipmmu_tlb_sync(domain);
479 ipmmu_domain_free_context(domain->mmu->root, domain->context_id); 493 ipmmu_domain_free_context(domain->mmu->root, domain->context_id);
480} 494}
@@ -490,11 +504,11 @@ static irqreturn_t ipmmu_domain_irq(struct ipmmu_vmsa_domain *domain)
490 u32 status; 504 u32 status;
491 u32 iova; 505 u32 iova;
492 506
493 status = ipmmu_ctx_read(domain, IMSTR); 507 status = ipmmu_ctx_read_root(domain, IMSTR);
494 if (!(status & err_mask)) 508 if (!(status & err_mask))
495 return IRQ_NONE; 509 return IRQ_NONE;
496 510
497 iova = ipmmu_ctx_read(domain, IMEAR); 511 iova = ipmmu_ctx_read_root(domain, IMEAR);
498 512
499 /* 513 /*
500 * Clear the error status flags. Unlike traditional interrupt flag 514 * Clear the error status flags. Unlike traditional interrupt flag
@@ -502,7 +516,7 @@ static irqreturn_t ipmmu_domain_irq(struct ipmmu_vmsa_domain *domain)
502 * seems to require 0. The error address register must be read before, 516 * seems to require 0. The error address register must be read before,
503 * otherwise its value will be 0. 517 * otherwise its value will be 0.
504 */ 518 */
505 ipmmu_ctx_write(domain, IMSTR, 0); 519 ipmmu_ctx_write_root(domain, IMSTR, 0);
506 520
507 /* Log fatal errors. */ 521 /* Log fatal errors. */
508 if (status & IMSTR_MHIT) 522 if (status & IMSTR_MHIT)