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: 6692981295
("iommu/amd: Add support for X2APIC IOMMU interrupts")
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
Link: https://lore.kernel.org/r/20211123161038.48009-4-mlevitsk@redhat.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
Родитель
01b297a48a
Коммит
4691f79d62
|
@ -2015,48 +2015,18 @@ union intcapxt {
|
||||||
};
|
};
|
||||||
} __attribute__ ((packed));
|
} __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 struct irq_chip intcapxt_controller;
|
||||||
|
|
||||||
static int intcapxt_irqdomain_activate(struct irq_domain *domain,
|
static int intcapxt_irqdomain_activate(struct irq_domain *domain,
|
||||||
struct irq_data *irqd, bool reserve)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intcapxt_irqdomain_deactivate(struct irq_domain *domain,
|
static void intcapxt_irqdomain_deactivate(struct irq_domain *domain,
|
||||||
struct irq_data *irqd)
|
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);
|
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,
|
static int intcapxt_set_affinity(struct irq_data *irqd,
|
||||||
const struct cpumask *mask, bool force)
|
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);
|
ret = parent->chip->irq_set_affinity(parent, mask, force);
|
||||||
if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE)
|
if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE)
|
||||||
return ret;
|
return ret;
|
||||||
|
return 0;
|
||||||
return intcapxt_irqdomain_activate(irqd->domain, irqd, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct irq_chip intcapxt_controller = {
|
static struct irq_chip intcapxt_controller = {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче