mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-22 13:54:57 +08:00
iommu/amd: X2apic mode: setup the INTX registers on mask/unmask
[ Upstream commit4691f79d62
] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
0210cbc1ef
commit
88c62a000b
@ -2012,48 +2012,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);
|
||||
}
|
||||
|
||||
|
||||
@ -2087,6 +2057,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)
|
||||
{
|
||||
@ -2096,8 +2098,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 = {
|
||||
|
Loading…
Reference in New Issue
Block a user