The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: wei.liu@kernel.org
To: Linux on Hyper-V List <linux-hyperv@vger.kernel.org>
Cc: mukeshrathor@linux.microsoft.com, anirudh@anirudhrb.com,
	schakrabarti@linux.microsoft.com, "Wei Liu" <wei.liu@kernel.org>,
	"K. Y. Srinivasan" <kys@microsoft.com>,
	"Haiyang Zhang" <haiyangz@microsoft.com>,
	"Dexuan Cui" <decui@microsoft.com>,
	"Long Li" <longli@microsoft.com>,
	"Lorenzo Pieralisi" <lpieralisi@kernel.org>,
	"Krzysztof Wilczyński" <kwilczynski@kernel.org>,
	"Manivannan Sadhasivam" <mani@kernel.org>,
	"Rob Herring" <robh@kernel.org>,
	"Bjorn Helgaas" <bhelgaas@google.com>,
	linux-pci@vger.kernel.org (open list:PCI NATIVE HOST BRIDGE AND
	ENDPOINT DRIVERS), linux-kernel@vger.kernel.org (open list)
Subject: [PATCH 3/3] PCI: hv: fix interrupt affinity change on the nested root partition
Date: Fri, 21 Aug 2026 17:36:22 -0700	[thread overview]
Message-ID: <20260822003623.2925128-4-wei.liu@kernel.org> (raw)
In-Reply-To: <20260822003623.2925128-1-wei.liu@kernel.org>

From: Wei Liu <wei.liu@kernel.org>

hv_compose_msi_msg() sends PCI_CREATE_INTERRUPT carrying
int_desc.vector, and the vPCI backend programs the device with the
address/data it returns for it.

An affinity change only ran irq_chip_set_affinity_parent(), which
re-allocates the x86 vector and nothing else, and hv_arch_irq_unmask()
then issued MAP_DEVICE_INTERRUPT for the new (VP, vector).  Nothing
re-composed the interrupt, so the device kept signalling the vector it
was created with and the new mapping was never used. This led to loss of
interrupts.

Do the re-target where the vector is known and the interrupt is
quiescent.  If the vector changed, re-compose the VMBus interrupt for
it, write the resulting message to the device, and only then map the new
(vp, vector); the old mapping is destroyed as the new message is
composed.

Signed-off-by: Wei Liu <wei.liu@kernel.org>
---
 drivers/pci/controller/pci-hyperv.c | 41 +++++++++++++++++++++++++++--
 1 file changed, 39 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index 5a36382742bf..5acb8e41567e 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -294,6 +294,7 @@ struct tran_int_desc {
 struct hv_msi_int_entry {
 	struct tran_int_desc		int_desc;
 	struct hv_interrupt_entry	hv_entry;
+	unsigned int			mapped_vector;
 };
 
 /* chip_data is passed around as a struct tran_int_desc *, so it must be first. */
@@ -742,6 +743,8 @@ static void hv_irq_retarget_interrupt(struct irq_data *data)
 			"%s() failed: %#llx", __func__, res);
 }
 
+static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg);
+
 static void hv_arch_irq_unmask(struct irq_data *data)
 {
 	if (hv_root_partition()) {
@@ -752,9 +755,17 @@ static void hv_arch_irq_unmask(struct irq_data *data)
 		 * RETARGET_INTERRUPT.
 		 *
 		 * Keep the returned entry so the mapping can be removed again
-		 * when the interrupt is torn down.
+		 * when the interrupt is re-targeted or torn down.
+		 *
+		 * This is also the re-target point.  The core calls us from
+		 * __irq_move_irq() with the interrupt masked once the new
+		 * vector has been assigned, so if the vector changed the vmbus
+		 * interrupt is re-composed for it first -- PCI_CREATE_INTERRUPT
+		 * carries the vector, so the device would otherwise keep
+		 * signalling the one it was created with.
 		 */
 		struct hv_msi_int_entry *ie = data->chip_data;
+		unsigned int vec = hv_msi_get_int_vector(data);
 
 		/*
 		 * A NULL chip_data means hv_compose_msi_msg() failed and the
@@ -763,8 +774,29 @@ static void hv_arch_irq_unmask(struct irq_data *data)
 		if (!ie)
 			return;
 
-		if (hv_map_msi_interrupt(data, &ie->hv_entry))
+		/* Already mapped for this vector, nothing changed. */
+		if (ie->mapped_vector == vec && ie->hv_entry.source)
+			return;
+
+		if (ie->mapped_vector && ie->mapped_vector != vec) {
+			struct msi_msg msg;
+
+			hv_compose_msi_msg(data, &msg);
+
+			ie = data->chip_data;
+			if (!ie)
+				return;
+
+			if (data->chip->irq_write_msi_msg)
+				data->chip->irq_write_msi_msg(data, &msg);
+		}
+
+		if (hv_map_msi_interrupt(data, &ie->hv_entry)) {
 			memset(&ie->hv_entry, 0, sizeof(ie->hv_entry));
+			ie->mapped_vector = 0;
+			return;
+		}
+		ie->mapped_vector = vec;
 	} else {
 		hv_irq_retarget_interrupt(data);
 	}
@@ -1974,6 +2006,11 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
 	if (data->chip_data && !multi_msi) {
 		int_desc = data->chip_data;
 		data->chip_data = NULL;
+		/*
+		 * The descriptor is about to be destroyed, so release the
+		 * hypervisor mapping that belongs to it first.
+		 */
+		hv_vmbus_unmap_msi_interrupt(pdev, int_desc);
 		hv_int_desc_free(hpdev, int_desc);
 	}
 
-- 
2.53.0


  parent reply	other threads:[~2026-08-22  0:36 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20260822003623.2925128-1-wei.liu@kernel.org>
2026-08-22  0:36 ` [PATCH 1/3] x86/hyperv: export hv_unmap_msi_interrupt() wei.liu
2026-08-25 17:25   ` [EXTERNAL] " Long Li
2026-08-22  0:36 ` [PATCH 2/3] PCI: hv: unmap MSI interrupt on the nested root partition teardown path wei.liu
2026-08-25 20:12   ` [EXTERNAL] " Long Li
2026-08-22  0:36 ` wei.liu [this message]
2026-08-25 20:33   ` [EXTERNAL] [PATCH 3/3] PCI: hv: fix interrupt affinity change on the nested root partition Long Li

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260822003623.2925128-4-wei.liu@kernel.org \
    --to=wei.liu@kernel.org \
    --cc=anirudh@anirudhrb.com \
    --cc=bhelgaas@google.com \
    --cc=decui@microsoft.com \
    --cc=haiyangz@microsoft.com \
    --cc=kwilczynski@kernel.org \
    --cc=kys@microsoft.com \
    --cc=linux-hyperv@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=longli@microsoft.com \
    --cc=lpieralisi@kernel.org \
    --cc=mani@kernel.org \
    --cc=mukeshrathor@linux.microsoft.com \
    --cc=robh@kernel.org \
    --cc=schakrabarti@linux.microsoft.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox