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

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.comSigned-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 01b297a4
......@@ -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 = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment