Skip to contentSkip to conversation

New Paravirtual front-end for PCI in a Hyper-V VM

PATCH Superseded [email protected] 4 participants 10 messages Aug 2, 2015 – Aug 3, 2015

Subsystems (4)

v1 of 10 Superseded Latest is v10 →

lore
Share & tools
lore
#0 lore raw

cover New Paravirtual front-end for PCI in a Hyper-V VM

From: Jake Oshins <[email protected]>

This patch series exposes the primitives necessary for an interrupt domain in a module and then introduces a new driver. This driver exposes a root PCI bus when running in a Hyper-V VM for each device which is passed through to the VM from the physical host.

This patch series differs from an earlier patch series in that the way interrupts are managed for the devices has been rewritten, this time to use IRQ domains, which allows the patches to be applied to the linux-next tree.

Jake Oshins (4):
drivers:hv: Export a function that maps Linux CPU num onto Hyper-V
proc num
drivers:hv: Define the channel type for Hyper-V PCI Express
pass-through
drivers:x86:pci: Make it possible to implement a PCI MSI IRQ Domain in
a module.
drivers:pci:hv: New paravirtual PCI front-end for Hyper-V VMs

 MAINTAINERS                    |    1 +
 arch/x86/kernel/apic/vector.c  |    2 +
 drivers/hv/vmbus_drv.c         |   17 +
 drivers/pci/Kconfig            |    7 +
 drivers/pci/host/Makefile      |    1 +
 drivers/pci/host/hv_pcifront.c | 2228 ++++++++++++++++++++++++++++++++++++++++
 drivers/pci/msi.c              |    1 +
 include/linux/hyperv.h         |   13 +
 kernel/irq/chip.c              |    1 +
 9 files changed, 2271 insertions(+)
 create mode 100644 drivers/pci/host/hv_pcifront.c
Signature · 1 line
1.9.1
#1 lore raw

PATCH 1/4 drivers:hv: Export a function that maps Linux CPU num onto Hyper-V proc num

From: Jake Oshins <[email protected]>

This patch exposes the mapping between Linux CPU number and Hyper-V virtual processor number. This is necessary because the hypervisor needs to know which virtual processors to target when making a mapping in the Interrupt Redirection Table in the I/O MMU.

---
 drivers/hv/vmbus_drv.c | 17 +++++++++++++++++
 include/linux/hyperv.h |  2 ++
 2 files changed, 19 insertions(+)
drivers/hv/vmbus_drv.c +17 -0
index 2064f31..5b1a019 100644
@@ -1153,6 +1153,23 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
 }
 EXPORT_SYMBOL_GPL(vmbus_allocate_mmio);
 
+/**
+ * vmbus_cpu_number_to_vp_number() - Map CPU to VP.
+ * @cpu_number: CPU number in Linux terms
+ *
+ * This function returns the mapping between the Linux processor
+ * number and the hypervisor's virtual processor number, useful
+ * in making hypercalls and such that talk about specific
+ * processors.
+ *
+ * Return: Virtual processor number in Hyper-V terms
+ */
+int vmbus_cpu_number_to_vp_number(int cpu_number)
+{
+	return hv_context.vp_index[cpu_number];
+}
+EXPORT_SYMBOL_GPL(vmbus_cpu_number_to_vp_number);
+
 static int vmbus_acpi_add(struct acpi_device *device)
 {
 	acpi_status result;
include/linux/hyperv.h +2 -0
index 54733d5..02393b6 100644
@@ -982,6 +982,8 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
 			resource_size_t size, resource_size_t align,
 			bool fb_overlap_ok);
 
+int vmbus_cpu_number_to_vp_number(int cpu_number);
+
 /**
  * VMBUS_DEVICE - macro used to describe a specific hyperv vmbus device
  *
Signature · 1 line
1.9.1
#2 lore raw

PATCH 2/4 drivers:hv: Define the channel type for Hyper-V PCI Express pass-through

In reply to [email protected]

From: Jake Oshins <[email protected]>

This patch defines the channel type for a paravirtual PCI front-end within a Hyper-V VM.

---
 include/linux/hyperv.h | 11 +++++++++++
 1 file changed, 11 insertions(+)
include/linux/hyperv.h +11 -0
index 02393b6..ab17332 100644
@@ -1139,6 +1139,17 @@ int vmbus_cpu_number_to_vp_number(int cpu_number);
 		}
 
 /*
+ * PCI Express Pass Through
+ * {44C4F61D-4444-4400-9D52-802E27EDE19F}
+ */
+
+#define HV_PCIE_GUID \
+	.guid = { \
+			0x1D, 0xF6, 0xC4, 0x44, 0x44, 0x44, 0x00, 0x44, \
+			0x9D, 0x52, 0x80, 0x2E, 0x27, 0xED, 0xE1, 0x9F \
+		}
+
+/*
  * Common header for Hyper-V ICs
  */
 
Signature · 1 line
1.9.1
#3 lore raw

PATCH 3/4 drivers:x86:pci: Make it possible to implement a PCI MSI IRQ Domain in a module.

In reply to [email protected]

From: Jake Oshins <[email protected]>

The Linux kernel already has the concept of IRQ domain, wherein a component can expose a set of IRQs which are managed by a particular interrupt controller chip or other subsystem. The PCI driver exposes the notion of an IRQ domain for Message-Signaled Interrupts (MSI) from PCI Express devices. This patch exposes the functions which are necessary to do this within a module, rather than just linked into the kernel itself.

I felt it made more sense to deliver an MSI IRQ domain as a module both so that the code wouldn't be loaded except when needed and also because the driver which needs this (which is the next patch in this series) is a module and itself depends on another module.

---
 arch/x86/kernel/apic/vector.c | 2 ++
 drivers/pci/msi.c             | 1 +
 kernel/irq/chip.c             | 1 +
 3 files changed, 4 insertions(+)
arch/x86/kernel/apic/vector.c +2 -0
index f47069e..67f7e68 100644
@@ -29,6 +29,7 @@ struct apic_chip_data {
 };
 
 struct irq_domain *x86_vector_domain;
+EXPORT_SYMBOL_GPL(x86_vector_domain);
 static DEFINE_RAW_SPINLOCK(vector_lock);
 static cpumask_var_t vector_cpumask;
 static struct irq_chip lapic_controller;
@@ -66,6 +67,7 @@ struct irq_cfg *irqd_cfg(struct irq_data *irq_data)
 
 	return data ? &data->cfg : NULL;
 }
+EXPORT_SYMBOL_GPL(irqd_cfg);
 
 struct irq_cfg *irq_cfg(unsigned int irq)
 {
drivers/pci/msi.c +1 -0
index 566de05..b118be1 100644
@@ -1276,6 +1276,7 @@ struct irq_domain *pci_msi_create_irq_domain(struct device_node *node,
 
 	return msi_create_irq_domain(node, info, parent);
 }
+EXPORT_SYMBOL_GPL(pci_msi_create_irq_domain);
 
 /**
  * pci_msi_domain_alloc_irqs - Allocate interrupts for @dev in @domain
kernel/irq/chip.c +1 -0
index 76f199d..3c82c44 100644
@@ -935,6 +935,7 @@ void irq_chip_ack_parent(struct irq_data *data)
 	data = data->parent_data;
 	data->chip->irq_ack(data);
 }
+EXPORT_SYMBOL_GPL(irq_chip_ack_parent);
 
 /**
  * irq_chip_mask_parent - Mask the parent interrupt
Signature · 1 line
1.9.1
#4 lore raw

PATCH 4/4 drivers:pci:hv: New paravirtual PCI front-end for Hyper-V VMs

In reply to [email protected]

From: Jake Oshins <[email protected]>

This patch introduces a driver which exposes a root PCI bus whenever a PCI Express device is passed through to a Hyper-V VM. The device can be single- or multi-function. The interrupts for the devices are managed by an IRQ domain, implemented within this driver.

---
 MAINTAINERS                    |    1 +
 drivers/pci/Kconfig            |    7 +
 drivers/pci/host/Makefile      |    1 +
 drivers/pci/host/hv_pcifront.c | 2228 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 2237 insertions(+)
 create mode 100644 drivers/pci/host/hv_pcifront.c
MAINTAINERS +1 -0
index 1b7917d..fa3a818 100644
@@ -4957,6 +4957,7 @@ F:	arch/x86/kernel/cpu/mshyperv.c
 F:	drivers/hid/hid-hyperv.c
 F:	drivers/hv/
 F:	drivers/input/serio/hyperv-keyboard.c
+F:	drivers/pci/host/hv_pcifront.c
 F:	drivers/net/hyperv/
 F:	drivers/scsi/storvsc_drv.c
 F:	drivers/video/fbdev/hyperv_fb.c
drivers/pci/Kconfig +7 -0
index 73de4ef..9b82d93 100644
@@ -118,4 +118,11 @@ config PCI_LABEL
 	def_bool y if (DMI || ACPI)
 	select NLS
 
+config HYPERV_VPCI
+        tristate "Hyper-V PCI Frontend"
+        depends on PCI && X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN
+        help
+          The PCI device frontend driver allows the kernel to import arbitrary
+          PCI devices from a PCI backend to support PCI driver domains.
+
 source "drivers/pci/host/Kconfig"
drivers/pci/host/Makefile +1 -0
index 140d66f..39581fb 100644
@@ -2,6 +2,7 @@ obj-$(CONFIG_PCIE_DW) += pcie-designware.o
 obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
 obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
 obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
+obj-$(CONFIG_HYPERV_VPCI) += hv_pcifront.o
 obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
 obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
 obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
drivers/pci/host/hv_pcifront.c new file +2228 -0

2,228 lines not on this page · raw message

Signature · 1 line
1.9.1
#5 lore raw

Re: [PATCH 4/4] drivers:pci:hv: New paravirtual PCI front-end for Hyper-V VMs

Quoted 7 lines · On Sun, 2 Aug 2015, [email protected] wrote:
drivers/pci/host/hv_pcifront.c new file +7 -0
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/mman.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>

drivers/pci/host/hv_pcifront.c line 37

Quoted 10 lines
drivers/pci/host/hv_pcifront.c new file +10 -0
+#include <linux/kthread.h>
+#include <linux/completion.h>
+#include <linux/notifier.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/semaphore.h>
+#include <linux/irqdomain.h>
+#include <asm/irqdomain.h>
+#include <linux/msi.h>

I seriously doubt, that you need all of these includes.

Quoted 5 lines
drivers/pci/host/hv_pcifront.c new file +5 -0
+/* Interrupt management hooks */
+
+/**
+ * hv_msi_free() - Free the MSI.
+ * @domain:	The interrupt domain pointer

drivers/pci/host/hv_pcifront.c line 640

Quoted 10 lines
drivers/pci/host/hv_pcifront.c new file +10 -0
+ * @info:	Extra MSI-related context
+ * @virq:	Identifies the IRQ.
+ *
+ * The Hyper-V parent partition and hypervisor are tracking the
+ * messages that are in use, keeping the interrupt redirection
+ * table up to date.  This callback sends a message that frees
+ * the the IRT entry and related tracking nonsense.
+ */
+void hv_msi_free(struct irq_domain *domain, struct msi_domain_info *info,
+		 unsigned int virq)

static?

Quoted 6 lines
drivers/pci/host/hv_pcifront.c new file +6 -0
+{
+	struct pci_delete_interrupt *int_pkt;
+	struct {
+		struct pci_packet pkt;
+		u8 buffer[sizeof(struct pci_delete_interrupt) -
+			  sizeof(struct pci_message)];

drivers/pci/host/hv_pcifront.c line 656

Quoted 10 lines
drivers/pci/host/hv_pcifront.c new file +10 -0
+	} ctxt;
+	struct hv_pcibus_device *hbus;
+	struct hv_pci_dev *hpdev;
+	struct irq_desc *desc;
+	struct msi_desc *msi;
+	struct tran_int_desc *int_desc;
+	struct irq_desc *irq_desc;
+
+	desc = irq_to_desc(virq);
+	msi = irq_desc_get_msi_desc(desc);

Why do you need to lookup the irq descriptor if you want the msi descriptor?

drivers/pci/host/hv_pcifront.c line 662

Quoted 6 lines
drivers/pci/host/hv_pcifront.c new file +6 -0
+	hbus = info->data;
+	hpdev = lookup_hv_dev(hbus, devfn_to_wslot(msi->dev->devfn));
+	if (!hpdev)
+		return;
+
+	int_desc = irq_get_handler_data(virq);

I don't think this is a proper storage point. The data is domain/chip specific, right? So, what's wrong with storing it in irq_data::chip_data?

drivers/pci/host/hv_pcifront.c line 673

Quoted 11 lines
drivers/pci/host/hv_pcifront.c new file +11 -0
+	if (int_desc) {
+		memset(&ctxt, 0, sizeof(ctxt));
+		int_pkt = (struct pci_delete_interrupt *)&ctxt.pkt.message;
+		int_pkt->message_type.message_type =
+			PCI_DELETE_INTERRUPT_MESSAGE;
+		int_pkt->wslot.slot = hpdev->desc.win_slot.slot;
+		int_pkt->int_desc = *int_desc;
+		vmbus_sendpacket(hbus->hdev->channel, int_pkt, sizeof(*int_pkt),
+				 (unsigned long)&ctxt.pkt, VM_PKT_DATA_INBAND,
+				 0);
+		kfree(int_desc);

Free before clearing the reference?

drivers/pci/host/hv_pcifront.c line 674

Quoted 1 line
drivers/pci/host/hv_pcifront.c new file +1 -0
+		irq_desc = irq_to_desc(virq);

Do you expect the descriptor to change between the lookup above and this one?

drivers/pci/host/hv_pcifront.c line 675

Quoted 1 line
drivers/pci/host/hv_pcifront.c new file +1 -0
+		irq_desc->irq_data.handler_data = NULL;

You are not supposed to fiddle in irq_desc or irq_data internals. We have helper functions for that.

drivers/pci/host/hv_pcifront.c line 682

Quoted 7 lines
drivers/pci/host/hv_pcifront.c new file +7 -0
+	}
+
+	hv_pcichild_dec(hpdev, hv_pcidev_ref_by_slot);
+}
+
+int hv_set_affinity(struct irq_data *data, const struct cpumask *dest,
+		    bool force)

static, if at all.

drivers/pci/host/hv_pcifront.c line 687

Quoted 5 lines
drivers/pci/host/hv_pcifront.c new file +5 -0
+{
+	struct irq_data *parent = data->parent_data;
+
+	return parent->chip->irq_set_affinity(parent, dest, force);
+}

irq_chip_set_affinity_parent ???

drivers/pci/host/hv_pcifront.c line 719

Quoted 12 lines
drivers/pci/host/hv_pcifront.c new file +12 -0
+/**
+ * hv_compose_msi_msg() - Supplies a valid MSI address/data
+ * @data:	Everything about this MSI
+ * @msg:	Buffer that is filled in by this function
+ *
+ * This function unpacks the IRQ looking for target CPU set, IDT
+ * vector and mode and sends a message to the parent partition
+ * asking for a mapping for that tuple in this partition.  The
+ * response supplies a data value and address to which that data
+ * should be written to trigger that interrupt.
+ */
+void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)

static ?

Quoted 43 lines
drivers/pci/host/hv_pcifront.c new file +43 -0
+{
+	struct irq_cfg *cfg = irqd_cfg(data);
+	struct hv_pcibus_device *hbus;
+	struct hv_pci_dev *hpdev;
+	struct pci_bus *pbus;
+	struct pci_create_interrupt *int_pkt;
+	struct compose_comp_ctxt comp;
+	struct tran_int_desc *int_desc;
+	struct irq_desc *irq_desc;
+	struct {
+		struct pci_packet pkt;
+		u8 buffer[sizeof(struct pci_create_interrupt) -
+			  sizeof(struct pci_message)];
+	} ctxt;
+	int cpu;
+	int ret;
+
+	pbus = data->msi_desc->dev->bus;
+	hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata);
+	hpdev = lookup_hv_dev(hbus, devfn_to_wslot(data->msi_desc->dev->devfn));
+
+	if (!hpdev)
+		goto return_null_message;
+
+	int_desc = kzalloc(sizeof(*int_desc), GFP_KERNEL);
+	if (!int_desc)
+		goto return_null_message;
+
+	memset(&ctxt, 0, sizeof(ctxt));
+	init_completion(&comp.comp_pkt.host_event);
+	ctxt.pkt.completion_func = hv_pci_compose_compl;
+	ctxt.pkt.compl_ctxt = &comp;
+	int_pkt = (struct pci_create_interrupt *)&ctxt.pkt.message;
+	int_pkt->message_type.message_type = PCI_CREATE_INTERRUPT_MESSAGE;
+	int_pkt->wslot.slot = hpdev->desc.win_slot.slot;
+	int_pkt->int_desc.vector = cfg->vector;
+	int_pkt->int_desc.vector_count = 1;
+	int_pkt->int_desc.delivery_mode =
+		(apic->irq_delivery_mode == dest_LowestPrio) ? 1 : 0;
+
+	/*
+	 * Cut down interrupt targets to a single processor. Hyper-V
+	 * currently only supports picking the target of an MSI by

drivers/pci/host/hv_pcifront.c line 772

Quoted 10 lines
drivers/pci/host/hv_pcifront.c new file +10 -0
+	 * sending a message to the parent partition and receiving a
+	 * response. This can't really work in the context of
+	 * irq_set_affinity, which sometimes needs to run in an environment
+	 * that can't wait for a completion.  Until a future version of
+	 * Hyper-V exists that can retarget an interrupt without waiting,
+	 * this code picks a single virtual processor as the target.  This
+	 * comment and the following lines should be deleted when that
+	 * happens.
+	 */
+	cpu = cpumask_any_and(data->affinity, cpu_online_mask);

We have accessors for this for a reason. data->affinity will be gone after 4.3-rc1.

drivers/pci/host/hv_pcifront.c line 785

Quoted 13 lines
drivers/pci/host/hv_pcifront.c new file +12 -0
+	cpumask_clear(data->affinity);
+	cpumask_set_cpu(cpu, data->affinity);
 
+	/*
+	 * This bit doesn't have to work on machines with more than 64
+	 * processors because Hyper-V only supports 64 in a guest.
+	 */
+	for_each_cpu(cpu, data->affinity) {
+		if (cpu_is_offline(cpu))
+			continue;
+		int_pkt->int_desc.cpu_mask |=
+			(1 << vmbus_cpu_number_to_vp_number(cpu));
+	}

ROTFL. What's the point of this loop? To find the single already known cpu which is in the mask?

Quoted 11 lines
drivers/pci/host/hv_pcifront.c new file +11 -0
+	ret = vmbus_sendpacket(hpdev->hbus->hdev->channel, int_pkt,
+			       sizeof(*int_pkt), (unsigned long)&ctxt.pkt,
+			       VM_PKT_DATA_INBAND,
+			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	if (!ret)
+		wait_for_completion(&comp.comp_pkt.host_event);
+
+	if (comp.comp_pkt.completion_status < 0) {
+		pr_err("Request for interrupt failed: 0x%x",
+		       comp.comp_pkt.completion_status);
+		goto return_null_message;

drivers/pci/host/hv_pcifront.c line 807

Quoted 10 lines
drivers/pci/host/hv_pcifront.c new file +10 -0
+	}
+
+	/*
+	 * Record the assignment so that this can be unwound later. Using
+	 * irq_set_handler_data() here would be appropriate, but the lock
+	 * it takes is already held.
+	 */
+	*int_desc = comp.int_desc;
+	irq_desc = irq_to_desc(data->irq);
+	irq_desc->irq_data.handler_data = int_desc;

You're really a fan of redundant lookups. How is irq_desc->irq_data going to be different from data?

drivers/pci/host/hv_pcifront.c line 817

Quoted 9 lines
drivers/pci/host/hv_pcifront.c new file +9 -0
+	/* Pass up the result. */
+	msg->address_hi = comp.int_desc.address >> 32;
+	msg->address_lo = comp.int_desc.address & 0xffffffff;
+	msg->data = comp.int_desc.data;
+
+	hv_pcichild_dec(hpdev, hv_pcidev_ref_by_slot);
+	return;
+
+return_null_message:

Leaks int_desc and a refcount on hpdev.

drivers/pci/host/hv_pcifront.c line 829

Quoted 11 lines
drivers/pci/host/hv_pcifront.c new file +11 -0
+	msg->address_hi = 0;
+	msg->address_lo = 0;
+	msg->data = 0;
+}
+
+/* HW Interrupt Chip Descriptor */
+static struct irq_chip hv_msi_irq_chip = {
+	.name = "Hyper-V PCIe MSI",
+	.irq_compose_msi_msg = hv_compose_msi_msg,
+	.irq_set_affinity = hv_set_affinity,
+	.irq_ack = irq_chip_ack_parent,

Please format this readable:

	.name			= "Hyper-V PCIe MSI",
	.irq_compose_msi_msg	= hv_compose_msi_msg,
	.irq_set_affinity	= hv_set_affinity,
	.irq_ack		= irq_chip_ack_parent,

Hmm?

Quoted 16 lines
drivers/pci/host/hv_pcifront.c new file +16 -0
+};
+
+static irq_hw_number_t hv_msi_domain_ops_get_hwirq(struct msi_domain_info *info,
+						   msi_alloc_info_t *arg)
+{
+	return arg->msi_hwirq;
+}
+
+static int hv_msi_domain_ops_prepare(struct irq_domain *domain,
+				     struct device *dev, int nvec,
+				     msi_alloc_info_t *arg)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct msi_desc *desc = first_pci_msi_entry(pdev);
+
+	memset(arg, 0, sizeof(*arg));

drivers/pci/host/hv_pcifront.c line 855

Quoted 10 lines
drivers/pci/host/hv_pcifront.c new file +10 -0
+	arg->msi_dev = pdev;
+	if (desc->msi_attrib.is_msix) {
+		arg->type = X86_IRQ_ALLOC_TYPE_MSIX;
+	} else {
+		arg->type = X86_IRQ_ALLOC_TYPE_MSI;
+		arg->flags |= X86_IRQ_ALLOC_CONTIGUOUS_VECTORS;
+	}
+
+	return 0;
+}

Pretty much a copy of the x86 code, right?

I wonder whether this MSI infrastructure code would be better seperated out and moved to arch/x86/hyperv/msi.c or arch/x86/kernel/apic/hvmsi.c. It's small enough to be built in. So all you'd need to export is hv_pcie_init_irq_domain and hv_pcie_free_irq_domain.

Thanks,

tglx

#6 lore raw

RE: [PATCH 4/4] drivers:pci:hv: New paravirtual PCI front-end for Hyper-V VMs

Quoted 12 lines

-----Original Message-----
From: Thomas Gleixner [mailto:[email protected]]
Sent: Sunday, August 2, 2015 1:47 AM
To: Jake Oshins <[email protected]>
Cc: [email protected]; KY Srinivasan <[email protected]>; LKML <[email protected]>; [email protected]; [email protected]; [email protected]; [email protected]; linux- [email protected]; [email protected]; [email protected]; Jiang Liu <[email protected]>
Subject: Re: [PATCH 4/4] drivers:pci:hv: New paravirtual PCI front-end for Hyper-V VMs

<snip>

Quoted 27 lines
Quoted 8 lines
drivers/pci/host/hv_pcifront.c new file +8 -0
+static int hv_msi_domain_ops_prepare(struct irq_domain *domain,
+				     struct device *dev, int nvec,
+				     msi_alloc_info_t *arg)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct msi_desc *desc = first_pci_msi_entry(pdev);
+
+	memset(arg, 0, sizeof(*arg));

drivers/pci/host/hv_pcifront.c line 855

Quoted 10 lines
drivers/pci/host/hv_pcifront.c new file +10 -0
+	arg->msi_dev = pdev;
+	if (desc->msi_attrib.is_msix) {
+		arg->type = X86_IRQ_ALLOC_TYPE_MSIX;
+	} else {
+		arg->type = X86_IRQ_ALLOC_TYPE_MSI;
+		arg->flags |= X86_IRQ_ALLOC_CONTIGUOUS_VECTORS;
+	}
+
+	return 0;
+}

Pretty much a copy of the x86 code, right?

I wonder whether this MSI infrastructure code would be better seperated out and moved to arch/x86/hyperv/msi.c or arch/x86/kernel/apic/hvmsi.c. It's small enough to be built in. So all you'd need to export is hv_pcie_init_irq_domain and hv_pcie_free_irq_domain.

Quoted 3 lines

Thanks,

tglx

Thanks for your review. I'll respond to all of your feedback and resend.

I do have a question about your last point, though. If I build this into the kernel, it will need to depend on sending and receiving messages through the hv_vmbus driver, which isn't built in. It seemed like the indirection and glue code necessary to make that work would be almost as big as this entire implementation (which admittedly isn't very big.) If you prefer that, I'll do it. But it would make more sense to me to refactor this a bit more so that functions like the one above are exported rather than putting hv_pcie_init_irq_domain and hv_pcie_free_irq_domain into the kernel itself. Would that work?

Thanks,
Jake Oshins

#7 lore raw

RE: [PATCH 4/4] drivers:pci:hv: New paravirtual PCI front-end for Hyper-V VMs

Quoted 3 lines · Jake Oshins

I do have a question about your last point, though. If I build this into the kernel, it will need to depend on sending and receiving messages through the hv_vmbus driver, which isn't built in. It

Fair enough. I missed that detail.

Quoted 7 lines

seemed like the indirection and glue code necessary to make that work would be almost as big as this entire implementation (which admittedly isn't very big.) If you prefer that, I'll do it. But it would make more sense to me to refactor this a bit more so that functions like the one above are exported rather than putting hv_pcie_init_irq_domain and hv_pcie_free_irq_domain into the kernel itself. Would that work?

Yes.

Thanks,

tglx

#8 lore raw

Re: [PATCH 4/4] drivers:pci:hv: New paravirtual PCI front-end for Hyper-V VMs

In reply to [email protected]
Quoted 10 lines · On zo, 2015-08-02 at 00:54 +0000, [email protected] wrote:
drivers/pci/host/hv_pcifront.c new file +7 -0
 
+static void exit_hv_pci_drv(void)
+{
+	vmbus_driver_unregister(&hv_pci_drv);
+}
+
+static int __init init_hv_pci_drv(void)
+{

drivers/pci/host/hv_pcifront.c line 2222

Quoted 10 lines
drivers/pci/host/hv_pcifront.c new file +10 -0
+	int ret;
+
+	/* Register this driver with VMBus. */
+	ret = vmbus_driver_register(&hv_pci_drv);
+
+	if (ret < 0)
+		exit_hv_pci_drv();
+
+	return ret;
+}

Wouldn't just

    static int __init init_hv_pci_drv(void)
    {
    	return vmbus_driver_register(&hv_pci_drv);
    }

suffice here? That would also allow to mark exit_hv_pci_drv() with __exit.

drivers/pci/host/hv_pcifront.c line 2225

Quoted 2 lines
drivers/pci/host/hv_pcifront.c new file +2 -0
+module_init(init_hv_pci_drv);
+module_exit(exit_hv_pci_drv);

Thanks,

Paul Bolle

#9 lore raw

Re: [PATCH 4/4] drivers:pci:hv: New paravirtual PCI front-end for Hyper-V VMs

Quoted 23 lines · Paul Bolle
Quoted 10 lines · On zo, 2015-08-02 at 00:54 +0000, [email protected] wrote:
drivers/pci/host/hv_pcifront.c new file +7 -0
 
+static void exit_hv_pci_drv(void)
+{
+	vmbus_driver_unregister(&hv_pci_drv);
+}
+
+static int __init init_hv_pci_drv(void)
+{

drivers/pci/host/hv_pcifront.c line 2222

Quoted 10 lines
drivers/pci/host/hv_pcifront.c new file +10 -0
+	int ret;
+
+	/* Register this driver with VMBus. */
+	ret = vmbus_driver_register(&hv_pci_drv);
+
+	if (ret < 0)
+		exit_hv_pci_drv();
+
+	return ret;
+}

Wouldn't just

Quoted 6 lines
    static int __init init_hv_pci_drv(void)
    {
    	return vmbus_driver_register(&hv_pci_drv);
    }

suffice here?

You're right, of course. The error handling is buggy.

regards,
dan carpenter