Commit 4691f79d authored by Maxim Levitsky's avatar Maxim Levitsky Committed by Joerg Roedel
Browse files

iommu/amd: X2apic mode: setup the INTX registers on mask/unmask



This is more logically correct and will also allow us to
to use mask/unmask logic to restore INTX setttings after
the resume from s3/s4.

Fixes: 66929812 ("iommu/amd: Add support for X2APIC IOMMU interrupts")

Signed-off-by: default avatarMaxim Levitsky <mlevitsk@redhat.com>
Link: https://lore.kernel.org/r/20211123161038.48009-4-mlevitsk@redhat.com


Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 01b297a4
Loading
Loading
Loading
Loading
+33 −32
Original line number Diff line number Diff line
@@ -2015,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);
}


@@ -2090,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)
{
@@ -2099,8 +2101,7 @@ 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 intcapxt_irqdomain_activate(irqd->domain, irqd, false);
	return 0;
}

static struct irq_chip intcapxt_controller = {