aboutsummaryrefslogtreecommitdiff
path: root/arch/s390/pci/pci_irq.c
diff options
context:
space:
mode:
authorAlexander Gordeev <[email protected]>2020-11-26 18:00:37 +0100
committerHeiko Carstens <[email protected]>2020-12-02 18:17:50 +0100
commita2bd4097b3ec242f4de4924db463a9c94530e03a (patch)
tree7fcbe0566342e1ccf1f5e97980ada18931f7a1b3 /arch/s390/pci/pci_irq.c
parentb65054597872ce3aefbc6a666385eabdf9e288da (diff)
s390/pci: fix CPU address in MSI for directed IRQ
The directed MSIs are delivered to CPUs whose address is written to the MSI message address. The current code assumes that a CPU logical number (as it is seen by the kernel) is also the CPU address. The above assumption is not correct, as the CPU address is rather the value returned by STAP instruction. That value does not necessarily match the kernel logical CPU number. Fixes: e979ce7bced2 ("s390/pci: provide support for CPU directed interrupts") Cc: <[email protected]> # v5.2+ Signed-off-by: Alexander Gordeev <[email protected]> Reviewed-by: Halil Pasic <[email protected]> Reviewed-by: Niklas Schnelle <[email protected]> Signed-off-by: Niklas Schnelle <[email protected]> Signed-off-by: Heiko Carstens <[email protected]>
Diffstat (limited to 'arch/s390/pci/pci_irq.c')
-rw-r--r--arch/s390/pci/pci_irq.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/arch/s390/pci/pci_irq.c b/arch/s390/pci/pci_irq.c
index 743f257cf2cb..75217fb63d7b 100644
--- a/arch/s390/pci/pci_irq.c
+++ b/arch/s390/pci/pci_irq.c
@@ -103,9 +103,10 @@ static int zpci_set_irq_affinity(struct irq_data *data, const struct cpumask *de
{
struct msi_desc *entry = irq_get_msi_desc(data->irq);
struct msi_msg msg = entry->msg;
+ int cpu_addr = smp_cpu_get_cpu_address(cpumask_first(dest));
msg.address_lo &= 0xff0000ff;
- msg.address_lo |= (cpumask_first(dest) << 8);
+ msg.address_lo |= (cpu_addr << 8);
pci_write_msi_msg(data->irq, &msg);
return IRQ_SET_MASK_OK;
@@ -238,6 +239,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
unsigned long bit;
struct msi_desc *msi;
struct msi_msg msg;
+ int cpu_addr;
int rc, irq;
zdev->aisb = -1UL;
@@ -287,9 +289,15 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
handle_percpu_irq);
msg.data = hwirq - bit;
if (irq_delivery == DIRECTED) {
+ if (msi->affinity)
+ cpu = cpumask_first(&msi->affinity->mask);
+ else
+ cpu = 0;
+ cpu_addr = smp_cpu_get_cpu_address(cpu);
+
msg.address_lo = zdev->msi_addr & 0xff0000ff;
- msg.address_lo |= msi->affinity ?
- (cpumask_first(&msi->affinity->mask) << 8) : 0;
+ msg.address_lo |= (cpu_addr << 8);
+
for_each_possible_cpu(cpu) {
airq_iv_set_data(zpci_ibv[cpu], hwirq, irq);
}