diff options
Diffstat (limited to 'drivers/iommu/amd/init.c')
| -rw-r--r-- | drivers/iommu/amd/init.c | 109 | 
1 files changed, 59 insertions, 50 deletions
| diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 1eacd43cb436..dc338acf3338 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -806,16 +806,27 @@ static int iommu_ga_log_enable(struct amd_iommu *iommu)  {  #ifdef CONFIG_IRQ_REMAP  	u32 status, i; +	u64 entry;  	if (!iommu->ga_log)  		return -EINVAL; -	status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); -  	/* Check if already running */ -	if (status & (MMIO_STATUS_GALOG_RUN_MASK)) +	status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); +	if (WARN_ON(status & (MMIO_STATUS_GALOG_RUN_MASK)))  		return 0; +	entry = iommu_virt_to_phys(iommu->ga_log) | GA_LOG_SIZE_512; +	memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_BASE_OFFSET, +		    &entry, sizeof(entry)); +	entry = (iommu_virt_to_phys(iommu->ga_log_tail) & +		 (BIT_ULL(52)-1)) & ~7ULL; +	memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_TAIL_OFFSET, +		    &entry, sizeof(entry)); +	writel(0x00, iommu->mmio_base + MMIO_GA_HEAD_OFFSET); +	writel(0x00, iommu->mmio_base + MMIO_GA_TAIL_OFFSET); + +  	iommu_feature_enable(iommu, CONTROL_GAINT_EN);  	iommu_feature_enable(iommu, CONTROL_GALOG_EN); @@ -825,7 +836,7 @@ static int iommu_ga_log_enable(struct amd_iommu *iommu)  			break;  	} -	if (i >= LOOP_TIMEOUT) +	if (WARN_ON(i >= LOOP_TIMEOUT))  		return -EINVAL;  #endif /* CONFIG_IRQ_REMAP */  	return 0; @@ -834,8 +845,6 @@ static int iommu_ga_log_enable(struct amd_iommu *iommu)  static int iommu_init_ga_log(struct amd_iommu *iommu)  {  #ifdef CONFIG_IRQ_REMAP -	u64 entry; -  	if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir))  		return 0; @@ -849,16 +858,6 @@ static int iommu_init_ga_log(struct amd_iommu *iommu)  	if (!iommu->ga_log_tail)  		goto err_out; -	entry = iommu_virt_to_phys(iommu->ga_log) | GA_LOG_SIZE_512; -	memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_BASE_OFFSET, -		    &entry, sizeof(entry)); -	entry = (iommu_virt_to_phys(iommu->ga_log_tail) & -		 (BIT_ULL(52)-1)) & ~7ULL; -	memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_TAIL_OFFSET, -		    &entry, sizeof(entry)); -	writel(0x00, iommu->mmio_base + MMIO_GA_HEAD_OFFSET); -	writel(0x00, iommu->mmio_base + MMIO_GA_TAIL_OFFSET); -  	return 0;  err_out:  	free_ga_log(iommu); @@ -1523,7 +1522,7 @@ static void amd_iommu_ats_write_check_workaround(struct amd_iommu *iommu)  }  /* - * This function clues the initialization function for one IOMMU + * This function glues the initialization function for one IOMMU   * together and also allocates the command buffer and programs the   * hardware. It does NOT enable the IOMMU. This is done afterwards.   */ @@ -2016,48 +2015,18 @@ union intcapxt {  	};  } __attribute__ ((packed)); -/* - * There isn't really any need to mask/unmask at the irqchip level because - * the 64-bit INTCAPXT registers can be updated atomically without tearing - * when the affinity is being updated. - */ -static void intcapxt_unmask_irq(struct irq_data *data) -{ -} - -static void intcapxt_mask_irq(struct irq_data *data) -{ -}  static struct irq_chip intcapxt_controller;  static int intcapxt_irqdomain_activate(struct irq_domain *domain,  				       struct irq_data *irqd, bool reserve)  { -	struct amd_iommu *iommu = irqd->chip_data; -	struct irq_cfg *cfg = irqd_cfg(irqd); -	union intcapxt xt; - -	xt.capxt = 0ULL; -	xt.dest_mode_logical = apic->dest_mode_logical; -	xt.vector = cfg->vector; -	xt.destid_0_23 = cfg->dest_apicid & GENMASK(23, 0); -	xt.destid_24_31 = cfg->dest_apicid >> 24; - -	/** -	 * Current IOMMU implemtation uses the same IRQ for all -	 * 3 IOMMU interrupts. -	 */ -	writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET); -	writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET); -	writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET);  	return 0;  }  static void intcapxt_irqdomain_deactivate(struct irq_domain *domain,  					  struct irq_data *irqd)  { -	intcapxt_mask_irq(irqd);  } @@ -2091,6 +2060,38 @@ static void intcapxt_irqdomain_free(struct irq_domain *domain, unsigned int virq  	irq_domain_free_irqs_top(domain, virq, nr_irqs);  } + +static void intcapxt_unmask_irq(struct irq_data *irqd) +{ +	struct amd_iommu *iommu = irqd->chip_data; +	struct irq_cfg *cfg = irqd_cfg(irqd); +	union intcapxt xt; + +	xt.capxt = 0ULL; +	xt.dest_mode_logical = apic->dest_mode_logical; +	xt.vector = cfg->vector; +	xt.destid_0_23 = cfg->dest_apicid & GENMASK(23, 0); +	xt.destid_24_31 = cfg->dest_apicid >> 24; + +	/** +	 * Current IOMMU implementation uses the same IRQ for all +	 * 3 IOMMU interrupts. +	 */ +	writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET); +	writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET); +	writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET); +} + +static void intcapxt_mask_irq(struct irq_data *irqd) +{ +	struct amd_iommu *iommu = irqd->chip_data; + +	writeq(0, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET); +	writeq(0, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET); +	writeq(0, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET); +} + +  static int intcapxt_set_affinity(struct irq_data *irqd,  				 const struct cpumask *mask, bool force)  { @@ -2100,8 +2101,12 @@ static int intcapxt_set_affinity(struct irq_data *irqd,  	ret = parent->chip->irq_set_affinity(parent, mask, force);  	if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE)  		return ret; +	return 0; +} -	return intcapxt_irqdomain_activate(irqd->domain, irqd, false); +static int intcapxt_set_wake(struct irq_data *irqd, unsigned int on) +{ +	return on ? -EOPNOTSUPP : 0;  }  static struct irq_chip intcapxt_controller = { @@ -2111,7 +2116,8 @@ static struct irq_chip intcapxt_controller = {  	.irq_ack		= irq_chip_ack_parent,  	.irq_retrigger		= irq_chip_retrigger_hierarchy,  	.irq_set_affinity       = intcapxt_set_affinity, -	.flags			= IRQCHIP_SKIP_SET_WAKE, +	.irq_set_wake		= intcapxt_set_wake, +	.flags			= IRQCHIP_MASK_ON_SUSPEND,  };  static const struct irq_domain_ops intcapxt_domain_ops = { @@ -2173,7 +2179,6 @@ static int iommu_setup_intcapxt(struct amd_iommu *iommu)  		return ret;  	} -	iommu_feature_enable(iommu, CONTROL_INTCAPXT_EN);  	return 0;  } @@ -2196,6 +2201,10 @@ static int iommu_init_irq(struct amd_iommu *iommu)  	iommu->int_enabled = true;  enable_faults: + +	if (amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE) +		iommu_feature_enable(iommu, CONTROL_INTCAPXT_EN); +  	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);  	if (iommu->ppr_log != NULL) |