linux-hyperv.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Patch v4 1/2] PCI: hv: Decouple the func definition in hv_dr_state from VSP message
@ 2020-01-13 20:08 longli
  2020-01-13 20:08 ` [Patch v4 2/2] PCI: hv: Add support for protocol 1.3 and support PCI_BUS_RELATIONS2 longli
  2020-01-22 21:42 ` [Patch v4 1/2] PCI: hv: Decouple the func definition in hv_dr_state from VSP message Long Li
  0 siblings, 2 replies; 6+ messages in thread
From: longli @ 2020-01-13 20:08 UTC (permalink / raw)
  To: K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger, Sasha Levin,
	Lorenzo Pieralisi, Andrew Murray, Bjorn Helgaas, linux-hyperv,
	linux-pci, linux-kernel
  Cc: Long Li

From: Long Li <longli@microsoft.com>

hv_dr_state is used to find present PCI devices on the bus. The structure
reuses struct pci_function_description from VSP message to describe a
device.

To prepare support for pci_function_description v2, decouple this
dependence in hv_dr_state so it can work with both v1 and v2 VSP messages.

There is no functionality change.

Signed-off-by: Long Li <longli@microsoft.com>
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
---
Changes
v2: Changed some spaces to tabs, changed failure code to -ENOMEM
v3: Revised comment for function hv_pci_devices_present(), reformatted patch title
v4: Fixed spelling

 drivers/pci/controller/pci-hyperv.c | 101 +++++++++++++++++++---------
 1 file changed, 70 insertions(+), 31 deletions(-)

diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index f1f300218fab..3b3e1967cf08 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -507,10 +507,24 @@ struct hv_dr_work {
 	struct hv_pcibus_device *bus;
 };
 
+struct hv_pcidev_description {
+	u16	v_id;	/* vendor ID */
+	u16	d_id;	/* device ID */
+	u8	rev;
+	u8	prog_intf;
+	u8	subclass;
+	u8	base_class;
+	u32	subsystem_id;
+	union	win_slot_encoding win_slot;
+	u32	ser;	/* serial number */
+	u32	flags;
+	u16	virtual_numa_node;
+};
+
 struct hv_dr_state {
 	struct list_head list_entry;
 	u32 device_count;
-	struct pci_function_description func[0];
+	struct hv_pcidev_description func[0];
 };
 
 enum hv_pcichild_state {
@@ -527,7 +541,7 @@ struct hv_pci_dev {
 	refcount_t refs;
 	enum hv_pcichild_state state;
 	struct pci_slot *pci_slot;
-	struct pci_function_description desc;
+	struct hv_pcidev_description desc;
 	bool reported_missing;
 	struct hv_pcibus_device *hbus;
 	struct work_struct wrk;
@@ -1862,7 +1876,7 @@ static void q_resource_requirements(void *context, struct pci_response *resp,
  * Return: Pointer to the new tracking struct
  */
 static struct hv_pci_dev *new_pcichild_device(struct hv_pcibus_device *hbus,
-		struct pci_function_description *desc)
+		struct hv_pcidev_description *desc)
 {
 	struct hv_pci_dev *hpdev;
 	struct pci_child_message *res_req;
@@ -1973,7 +1987,7 @@ static void pci_devices_present_work(struct work_struct *work)
 {
 	u32 child_no;
 	bool found;
-	struct pci_function_description *new_desc;
+	struct hv_pcidev_description *new_desc;
 	struct hv_pci_dev *hpdev;
 	struct hv_pcibus_device *hbus;
 	struct list_head removed;
@@ -2090,43 +2104,26 @@ static void pci_devices_present_work(struct work_struct *work)
 	put_hvpcibus(hbus);
 	kfree(dr);
 }
-
 /**
- * hv_pci_devices_present() - Handles list of new children
+ * hv_pci_start_relations_work() - Queue work to start device discovery
  * @hbus:	Root PCI bus, as understood by this driver
- * @relations:	Packet from host listing children
+ * @dr:		The list of children returned from host
  *
- * This function is invoked whenever a new list of devices for
- * this bus appears.
+ * Return:  0 on success, -errno on failure
  */
-static void hv_pci_devices_present(struct hv_pcibus_device *hbus,
-				   struct pci_bus_relations *relations)
+static int hv_pci_start_relations_work(struct hv_pcibus_device *hbus,
+				       struct hv_dr_state *dr)
 {
-	struct hv_dr_state *dr;
 	struct hv_dr_work *dr_wrk;
-	unsigned long flags;
 	bool pending_dr;
+	unsigned long flags;
 
 	dr_wrk = kzalloc(sizeof(*dr_wrk), GFP_NOWAIT);
 	if (!dr_wrk)
-		return;
-
-	dr = kzalloc(offsetof(struct hv_dr_state, func) +
-		     (sizeof(struct pci_function_description) *
-		      (relations->device_count)), GFP_NOWAIT);
-	if (!dr)  {
-		kfree(dr_wrk);
-		return;
-	}
+		return -ENOMEM;
 
 	INIT_WORK(&dr_wrk->wrk, pci_devices_present_work);
 	dr_wrk->bus = hbus;
-	dr->device_count = relations->device_count;
-	if (dr->device_count != 0) {
-		memcpy(dr->func, relations->func,
-		       sizeof(struct pci_function_description) *
-		       dr->device_count);
-	}
 
 	spin_lock_irqsave(&hbus->device_list_lock, flags);
 	/*
@@ -2144,6 +2141,47 @@ static void hv_pci_devices_present(struct hv_pcibus_device *hbus,
 		get_hvpcibus(hbus);
 		queue_work(hbus->wq, &dr_wrk->wrk);
 	}
+
+	return 0;
+}
+
+/**
+ * hv_pci_devices_present() - Handle list of new children
+ * @hbus:	Root PCI bus, as understood by this driver
+ * @relations:	Packet from host listing children
+ *
+ * Process a new list of devices on the bus. The list of devices is
+ * discovered by VSP and sent to us via VSP message PCI_BUS_RELATIONS,
+ * whenever a new list of devices for this bus appears.
+ */
+static void hv_pci_devices_present(struct hv_pcibus_device *hbus,
+				   struct pci_bus_relations *relations)
+{
+	struct hv_dr_state *dr;
+	int i;
+
+	dr = kzalloc(offsetof(struct hv_dr_state, func) +
+		     (sizeof(struct hv_pcidev_description) *
+		      (relations->device_count)), GFP_NOWAIT);
+
+	if (!dr)
+		return;
+
+	dr->device_count = relations->device_count;
+	for (i = 0; i < dr->device_count; i++) {
+		dr->func[i].v_id = relations->func[i].v_id;
+		dr->func[i].d_id = relations->func[i].d_id;
+		dr->func[i].rev = relations->func[i].rev;
+		dr->func[i].prog_intf = relations->func[i].prog_intf;
+		dr->func[i].subclass = relations->func[i].subclass;
+		dr->func[i].base_class = relations->func[i].base_class;
+		dr->func[i].subsystem_id = relations->func[i].subsystem_id;
+		dr->func[i].win_slot = relations->func[i].win_slot;
+		dr->func[i].ser = relations->func[i].ser;
+	}
+
+	if (hv_pci_start_relations_work(hbus, dr))
+		kfree(dr);
 }
 
 /**
@@ -3018,7 +3056,7 @@ static void hv_pci_bus_exit(struct hv_device *hdev)
 		struct pci_packet teardown_packet;
 		u8 buffer[sizeof(struct pci_message)];
 	} pkt;
-	struct pci_bus_relations relations;
+	struct hv_dr_state *dr;
 	struct hv_pci_compl comp_pkt;
 	int ret;
 
@@ -3030,8 +3068,9 @@ static void hv_pci_bus_exit(struct hv_device *hdev)
 		return;
 
 	/* Delete any children which might still exist. */
-	memset(&relations, 0, sizeof(relations));
-	hv_pci_devices_present(hbus, &relations);
+	dr = kzalloc(sizeof(*dr), GFP_KERNEL);
+	if (dr && hv_pci_start_relations_work(hbus, dr))
+		kfree(dr);
 
 	ret = hv_send_resources_released(hdev);
 	if (ret)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Patch v4 2/2] PCI: hv: Add support for protocol 1.3 and support PCI_BUS_RELATIONS2
  2020-01-13 20:08 [Patch v4 1/2] PCI: hv: Decouple the func definition in hv_dr_state from VSP message longli
@ 2020-01-13 20:08 ` longli
  2020-02-25 10:36   ` Lorenzo Pieralisi
  2020-01-22 21:42 ` [Patch v4 1/2] PCI: hv: Decouple the func definition in hv_dr_state from VSP message Long Li
  1 sibling, 1 reply; 6+ messages in thread
From: longli @ 2020-01-13 20:08 UTC (permalink / raw)
  To: K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger, Sasha Levin,
	Lorenzo Pieralisi, Andrew Murray, Bjorn Helgaas, linux-hyperv,
	linux-pci, linux-kernel
  Cc: Long Li

From: Long Li <longli@microsoft.com>

Starting with Hyper-V PCI protocol version 1.3, the host VSP can send
PCI_BUS_RELATIONS2 and pass the vNUMA node information for devices on the
bus. The vNUMA node tells which guest NUMA node this device is on based
on guest VM configuration topology and physical device inforamtion.

Add code to negotiate v1.3 and process PCI_BUS_RELATIONS2.

Signed-off-by: Long Li <longli@microsoft.com>
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
---
Changes
v2: Changed some spaces to tabs, added put_pcichild() after get_pcichild_wslot(), renamed pci_assign_numa_node() to hv_pci_assign_numa_node()
v4: Fixed spelling

 drivers/pci/controller/pci-hyperv.c | 109 ++++++++++++++++++++++++++++
 1 file changed, 109 insertions(+)

diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index 3b3e1967cf08..147358fae8a2 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -63,6 +63,7 @@
 enum pci_protocol_version_t {
 	PCI_PROTOCOL_VERSION_1_1 = PCI_MAKE_VERSION(1, 1),	/* Win10 */
 	PCI_PROTOCOL_VERSION_1_2 = PCI_MAKE_VERSION(1, 2),	/* RS1 */
+	PCI_PROTOCOL_VERSION_1_3 = PCI_MAKE_VERSION(1, 3),	/* Vibranium */
 };
 
 #define CPU_AFFINITY_ALL	-1ULL
@@ -72,6 +73,7 @@ enum pci_protocol_version_t {
  * first.
  */
 static enum pci_protocol_version_t pci_protocol_versions[] = {
+	PCI_PROTOCOL_VERSION_1_3,
 	PCI_PROTOCOL_VERSION_1_2,
 	PCI_PROTOCOL_VERSION_1_1,
 };
@@ -124,6 +126,7 @@ enum pci_message_type {
 	PCI_RESOURCES_ASSIGNED2		= PCI_MESSAGE_BASE + 0x16,
 	PCI_CREATE_INTERRUPT_MESSAGE2	= PCI_MESSAGE_BASE + 0x17,
 	PCI_DELETE_INTERRUPT_MESSAGE2	= PCI_MESSAGE_BASE + 0x18, /* unused */
+	PCI_BUS_RELATIONS2		= PCI_MESSAGE_BASE + 0x19,
 	PCI_MESSAGE_MAXIMUM
 };
 
@@ -169,6 +172,26 @@ struct pci_function_description {
 	u32	ser;	/* serial number */
 } __packed;
 
+enum pci_device_description_flags {
+	HV_PCI_DEVICE_FLAG_NONE			= 0x0,
+	HV_PCI_DEVICE_FLAG_NUMA_AFFINITY	= 0x1,
+};
+
+struct pci_function_description2 {
+	u16	v_id;	/* vendor ID */
+	u16	d_id;	/* device ID */
+	u8	rev;
+	u8	prog_intf;
+	u8	subclass;
+	u8	base_class;
+	u32	subsystem_id;
+	union	win_slot_encoding win_slot;
+	u32	ser;	/* serial number */
+	u32	flags;
+	u16	virtual_numa_node;
+	u16	reserved;
+} __packed;
+
 /**
  * struct hv_msi_desc
  * @vector:		IDT entry
@@ -304,6 +327,12 @@ struct pci_bus_relations {
 	struct pci_function_description func[0];
 } __packed;
 
+struct pci_bus_relations2 {
+	struct pci_incoming_message incoming;
+	u32 device_count;
+	struct pci_function_description2 func[0];
+} __packed;
+
 struct pci_q_res_req_response {
 	struct vmpacket_descriptor hdr;
 	s32 status;			/* negative values are failures */
@@ -1417,6 +1446,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
 		break;
 
 	case PCI_PROTOCOL_VERSION_1_2:
+	case PCI_PROTOCOL_VERSION_1_3:
 		size = hv_compose_msi_req_v2(&ctxt.int_pkts.v2,
 					dest,
 					hpdev->desc.win_slot.slot,
@@ -1798,6 +1828,27 @@ static void hv_pci_remove_slots(struct hv_pcibus_device *hbus)
 	}
 }
 
+/*
+ * Set NUMA node for the devices on the bus
+ */
+static void hv_pci_assign_numa_node(struct hv_pcibus_device *hbus)
+{
+	struct pci_dev *dev;
+	struct pci_bus *bus = hbus->pci_bus;
+	struct hv_pci_dev *hv_dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		hv_dev = get_pcichild_wslot(hbus, devfn_to_wslot(dev->devfn));
+		if (!hv_dev)
+			continue;
+
+		if (hv_dev->desc.flags & HV_PCI_DEVICE_FLAG_NUMA_AFFINITY)
+			set_dev_node(&dev->dev, hv_dev->desc.virtual_numa_node);
+
+		put_pcichild(hv_dev);
+	}
+}
+
 /**
  * create_root_hv_pci_bus() - Expose a new root PCI bus
  * @hbus:	Root PCI bus, as understood by this driver
@@ -1820,6 +1871,7 @@ static int create_root_hv_pci_bus(struct hv_pcibus_device *hbus)
 
 	pci_lock_rescan_remove();
 	pci_scan_child_bus(hbus->pci_bus);
+	hv_pci_assign_numa_node(hbus);
 	pci_bus_assign_resources(hbus->pci_bus);
 	hv_pci_assign_slots(hbus);
 	pci_bus_add_devices(hbus->pci_bus);
@@ -2088,6 +2140,7 @@ static void pci_devices_present_work(struct work_struct *work)
 		 */
 		pci_lock_rescan_remove();
 		pci_scan_child_bus(hbus->pci_bus);
+		hv_pci_assign_numa_node(hbus);
 		hv_pci_assign_slots(hbus);
 		pci_unlock_rescan_remove();
 		break;
@@ -2184,6 +2237,46 @@ static void hv_pci_devices_present(struct hv_pcibus_device *hbus,
 		kfree(dr);
 }
 
+/**
+ * hv_pci_devices_present2() - Handle list of new children
+ * @hbus:	Root PCI bus, as understood by this driver
+ * @relations2:	Packet from host listing children
+ *
+ * This function is the v2 version of hv_pci_devices_present()
+ */
+static void hv_pci_devices_present2(struct hv_pcibus_device *hbus,
+				    struct pci_bus_relations2 *relations)
+{
+	struct hv_dr_state *dr;
+	int i;
+
+	dr = kzalloc(offsetof(struct hv_dr_state, func) +
+		     (sizeof(struct hv_pcidev_description) *
+		      (relations->device_count)), GFP_NOWAIT);
+
+	if (!dr)
+		return;
+
+	dr->device_count = relations->device_count;
+	for (i = 0; i < dr->device_count; i++) {
+		dr->func[i].v_id = relations->func[i].v_id;
+		dr->func[i].d_id = relations->func[i].d_id;
+		dr->func[i].rev = relations->func[i].rev;
+		dr->func[i].prog_intf = relations->func[i].prog_intf;
+		dr->func[i].subclass = relations->func[i].subclass;
+		dr->func[i].base_class = relations->func[i].base_class;
+		dr->func[i].subsystem_id = relations->func[i].subsystem_id;
+		dr->func[i].win_slot = relations->func[i].win_slot;
+		dr->func[i].ser = relations->func[i].ser;
+		dr->func[i].flags = relations->func[i].flags;
+		dr->func[i].virtual_numa_node =
+			relations->func[i].virtual_numa_node;
+	}
+
+	if (hv_pci_start_relations_work(hbus, dr))
+		kfree(dr);
+}
+
 /**
  * hv_eject_device_work() - Asynchronously handles ejection
  * @work:	Work struct embedded in internal device struct
@@ -2289,6 +2382,7 @@ static void hv_pci_onchannelcallback(void *context)
 	struct pci_response *response;
 	struct pci_incoming_message *new_message;
 	struct pci_bus_relations *bus_rel;
+	struct pci_bus_relations2 *bus_rel2;
 	struct pci_dev_inval_block *inval;
 	struct pci_dev_incoming *dev_message;
 	struct hv_pci_dev *hpdev;
@@ -2356,6 +2450,21 @@ static void hv_pci_onchannelcallback(void *context)
 				hv_pci_devices_present(hbus, bus_rel);
 				break;
 
+			case PCI_BUS_RELATIONS2:
+
+				bus_rel2 = (struct pci_bus_relations2 *)buffer;
+				if (bytes_recvd <
+				    offsetof(struct pci_bus_relations2, func) +
+				    (sizeof(struct pci_function_description2) *
+				     (bus_rel2->device_count))) {
+					dev_err(&hbus->hdev->device,
+						"bus relations v2 too small\n");
+					break;
+				}
+
+				hv_pci_devices_present2(hbus, bus_rel2);
+				break;
+
 			case PCI_EJECT:
 
 				dev_message = (struct pci_dev_incoming *)buffer;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* RE: [Patch v4 1/2] PCI: hv: Decouple the func definition in hv_dr_state from VSP message
  2020-01-13 20:08 [Patch v4 1/2] PCI: hv: Decouple the func definition in hv_dr_state from VSP message longli
  2020-01-13 20:08 ` [Patch v4 2/2] PCI: hv: Add support for protocol 1.3 and support PCI_BUS_RELATIONS2 longli
@ 2020-01-22 21:42 ` Long Li
  2020-02-06 23:48   ` Long Li
  1 sibling, 1 reply; 6+ messages in thread
From: Long Li @ 2020-01-22 21:42 UTC (permalink / raw)
  To: longli, KY Srinivasan, Haiyang Zhang, Stephen Hemminger,
	Sasha Levin, Lorenzo Pieralisi, Andrew Murray, Bjorn Helgaas,
	linux-hyperv, linux-pci, linux-kernel

Hi Lorenzo,

Can you take a look at this patch?

Thanks

Long

>Subject: [Patch v4 1/2] PCI: hv: Decouple the func definition in hv_dr_state from
>VSP message
>
>From: Long Li <longli@microsoft.com>
>
>hv_dr_state is used to find present PCI devices on the bus. The structure reuses
>struct pci_function_description from VSP message to describe a device.
>
>To prepare support for pci_function_description v2, decouple this dependence in
>hv_dr_state so it can work with both v1 and v2 VSP messages.
>
>There is no functionality change.
>
>Signed-off-by: Long Li <longli@microsoft.com>
>Reviewed-by: Michael Kelley <mikelley@microsoft.com>
>---
>Changes
>v2: Changed some spaces to tabs, changed failure code to -ENOMEM
>v3: Revised comment for function hv_pci_devices_present(), reformatted patch
>title
>v4: Fixed spelling
>
> drivers/pci/controller/pci-hyperv.c | 101 +++++++++++++++++++---------
> 1 file changed, 70 insertions(+), 31 deletions(-)
>
>diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-
>hyperv.c
>index f1f300218fab..3b3e1967cf08 100644
>--- a/drivers/pci/controller/pci-hyperv.c
>+++ b/drivers/pci/controller/pci-hyperv.c
>@@ -507,10 +507,24 @@ struct hv_dr_work {
> 	struct hv_pcibus_device *bus;
> };
>
>+struct hv_pcidev_description {
>+	u16	v_id;	/* vendor ID */
>+	u16	d_id;	/* device ID */
>+	u8	rev;
>+	u8	prog_intf;
>+	u8	subclass;
>+	u8	base_class;
>+	u32	subsystem_id;
>+	union	win_slot_encoding win_slot;
>+	u32	ser;	/* serial number */
>+	u32	flags;
>+	u16	virtual_numa_node;
>+};
>+
> struct hv_dr_state {
> 	struct list_head list_entry;
> 	u32 device_count;
>-	struct pci_function_description func[0];
>+	struct hv_pcidev_description func[0];
> };
>
> enum hv_pcichild_state {
>@@ -527,7 +541,7 @@ struct hv_pci_dev {
> 	refcount_t refs;
> 	enum hv_pcichild_state state;
> 	struct pci_slot *pci_slot;
>-	struct pci_function_description desc;
>+	struct hv_pcidev_description desc;
> 	bool reported_missing;
> 	struct hv_pcibus_device *hbus;
> 	struct work_struct wrk;
>@@ -1862,7 +1876,7 @@ static void q_resource_requirements(void *context,
>struct pci_response *resp,
>  * Return: Pointer to the new tracking struct
>  */
> static struct hv_pci_dev *new_pcichild_device(struct hv_pcibus_device *hbus,
>-		struct pci_function_description *desc)
>+		struct hv_pcidev_description *desc)
> {
> 	struct hv_pci_dev *hpdev;
> 	struct pci_child_message *res_req;
>@@ -1973,7 +1987,7 @@ static void pci_devices_present_work(struct
>work_struct *work)  {
> 	u32 child_no;
> 	bool found;
>-	struct pci_function_description *new_desc;
>+	struct hv_pcidev_description *new_desc;
> 	struct hv_pci_dev *hpdev;
> 	struct hv_pcibus_device *hbus;
> 	struct list_head removed;
>@@ -2090,43 +2104,26 @@ static void pci_devices_present_work(struct
>work_struct *work)
> 	put_hvpcibus(hbus);
> 	kfree(dr);
> }
>-
> /**
>- * hv_pci_devices_present() - Handles list of new children
>+ * hv_pci_start_relations_work() - Queue work to start device discovery
>  * @hbus:	Root PCI bus, as understood by this driver
>- * @relations:	Packet from host listing children
>+ * @dr:		The list of children returned from host
>  *
>- * This function is invoked whenever a new list of devices for
>- * this bus appears.
>+ * Return:  0 on success, -errno on failure
>  */
>-static void hv_pci_devices_present(struct hv_pcibus_device *hbus,
>-				   struct pci_bus_relations *relations)
>+static int hv_pci_start_relations_work(struct hv_pcibus_device *hbus,
>+				       struct hv_dr_state *dr)
> {
>-	struct hv_dr_state *dr;
> 	struct hv_dr_work *dr_wrk;
>-	unsigned long flags;
> 	bool pending_dr;
>+	unsigned long flags;
>
> 	dr_wrk = kzalloc(sizeof(*dr_wrk), GFP_NOWAIT);
> 	if (!dr_wrk)
>-		return;
>-
>-	dr = kzalloc(offsetof(struct hv_dr_state, func) +
>-		     (sizeof(struct pci_function_description) *
>-		      (relations->device_count)), GFP_NOWAIT);
>-	if (!dr)  {
>-		kfree(dr_wrk);
>-		return;
>-	}
>+		return -ENOMEM;
>
> 	INIT_WORK(&dr_wrk->wrk, pci_devices_present_work);
> 	dr_wrk->bus = hbus;
>-	dr->device_count = relations->device_count;
>-	if (dr->device_count != 0) {
>-		memcpy(dr->func, relations->func,
>-		       sizeof(struct pci_function_description) *
>-		       dr->device_count);
>-	}
>
> 	spin_lock_irqsave(&hbus->device_list_lock, flags);
> 	/*
>@@ -2144,6 +2141,47 @@ static void hv_pci_devices_present(struct
>hv_pcibus_device *hbus,
> 		get_hvpcibus(hbus);
> 		queue_work(hbus->wq, &dr_wrk->wrk);
> 	}
>+
>+	return 0;
>+}
>+
>+/**
>+ * hv_pci_devices_present() - Handle list of new children
>+ * @hbus:	Root PCI bus, as understood by this driver
>+ * @relations:	Packet from host listing children
>+ *
>+ * Process a new list of devices on the bus. The list of devices is
>+ * discovered by VSP and sent to us via VSP message PCI_BUS_RELATIONS,
>+ * whenever a new list of devices for this bus appears.
>+ */
>+static void hv_pci_devices_present(struct hv_pcibus_device *hbus,
>+				   struct pci_bus_relations *relations) {
>+	struct hv_dr_state *dr;
>+	int i;
>+
>+	dr = kzalloc(offsetof(struct hv_dr_state, func) +
>+		     (sizeof(struct hv_pcidev_description) *
>+		      (relations->device_count)), GFP_NOWAIT);
>+
>+	if (!dr)
>+		return;
>+
>+	dr->device_count = relations->device_count;
>+	for (i = 0; i < dr->device_count; i++) {
>+		dr->func[i].v_id = relations->func[i].v_id;
>+		dr->func[i].d_id = relations->func[i].d_id;
>+		dr->func[i].rev = relations->func[i].rev;
>+		dr->func[i].prog_intf = relations->func[i].prog_intf;
>+		dr->func[i].subclass = relations->func[i].subclass;
>+		dr->func[i].base_class = relations->func[i].base_class;
>+		dr->func[i].subsystem_id = relations->func[i].subsystem_id;
>+		dr->func[i].win_slot = relations->func[i].win_slot;
>+		dr->func[i].ser = relations->func[i].ser;
>+	}
>+
>+	if (hv_pci_start_relations_work(hbus, dr))
>+		kfree(dr);
> }
>
> /**
>@@ -3018,7 +3056,7 @@ static void hv_pci_bus_exit(struct hv_device *hdev)
> 		struct pci_packet teardown_packet;
> 		u8 buffer[sizeof(struct pci_message)];
> 	} pkt;
>-	struct pci_bus_relations relations;
>+	struct hv_dr_state *dr;
> 	struct hv_pci_compl comp_pkt;
> 	int ret;
>
>@@ -3030,8 +3068,9 @@ static void hv_pci_bus_exit(struct hv_device *hdev)
> 		return;
>
> 	/* Delete any children which might still exist. */
>-	memset(&relations, 0, sizeof(relations));
>-	hv_pci_devices_present(hbus, &relations);
>+	dr = kzalloc(sizeof(*dr), GFP_KERNEL);
>+	if (dr && hv_pci_start_relations_work(hbus, dr))
>+		kfree(dr);
>
> 	ret = hv_send_resources_released(hdev);
> 	if (ret)
>--
>2.17.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* RE: [Patch v4 1/2] PCI: hv: Decouple the func definition in hv_dr_state from VSP message
  2020-01-22 21:42 ` [Patch v4 1/2] PCI: hv: Decouple the func definition in hv_dr_state from VSP message Long Li
@ 2020-02-06 23:48   ` Long Li
  0 siblings, 0 replies; 6+ messages in thread
From: Long Li @ 2020-02-06 23:48 UTC (permalink / raw)
  To: Long Li, longli, KY Srinivasan, Haiyang Zhang, Stephen Hemminger,
	Sasha Levin, Lorenzo Pieralisi, Andrew Murray, Bjorn Helgaas,
	linux-hyperv, linux-pci, linux-kernel

Hi guys,

Ping again...

Please take a look at these two patches.

Thanks

Long

>Subject: RE: [Patch v4 1/2] PCI: hv: Decouple the func definition in hv_dr_state
>from VSP message
>
>Hi Lorenzo,
>
>Can you take a look at this patch?
>
>Thanks
>
>Long
>
>>Subject: [Patch v4 1/2] PCI: hv: Decouple the func definition in
>>hv_dr_state from VSP message
>>
>>From: Long Li <longli@microsoft.com>
>>
>>hv_dr_state is used to find present PCI devices on the bus. The
>>structure reuses struct pci_function_description from VSP message to describe
>a device.
>>
>>To prepare support for pci_function_description v2, decouple this
>>dependence in hv_dr_state so it can work with both v1 and v2 VSP messages.
>>
>>There is no functionality change.
>>
>>Signed-off-by: Long Li <longli@microsoft.com>
>>Reviewed-by: Michael Kelley <mikelley@microsoft.com>
>>---
>>Changes
>>v2: Changed some spaces to tabs, changed failure code to -ENOMEM
>>v3: Revised comment for function hv_pci_devices_present(), reformatted
>>patch title
>>v4: Fixed spelling
>>
>> drivers/pci/controller/pci-hyperv.c | 101 +++++++++++++++++++---------
>> 1 file changed, 70 insertions(+), 31 deletions(-)
>>
>>diff --git a/drivers/pci/controller/pci-hyperv.c
>>b/drivers/pci/controller/pci- hyperv.c index f1f300218fab..3b3e1967cf08
>>100644
>>--- a/drivers/pci/controller/pci-hyperv.c
>>+++ b/drivers/pci/controller/pci-hyperv.c
>>@@ -507,10 +507,24 @@ struct hv_dr_work {
>> 	struct hv_pcibus_device *bus;
>> };
>>
>>+struct hv_pcidev_description {
>>+	u16	v_id;	/* vendor ID */
>>+	u16	d_id;	/* device ID */
>>+	u8	rev;
>>+	u8	prog_intf;
>>+	u8	subclass;
>>+	u8	base_class;
>>+	u32	subsystem_id;
>>+	union	win_slot_encoding win_slot;
>>+	u32	ser;	/* serial number */
>>+	u32	flags;
>>+	u16	virtual_numa_node;
>>+};
>>+
>> struct hv_dr_state {
>> 	struct list_head list_entry;
>> 	u32 device_count;
>>-	struct pci_function_description func[0];
>>+	struct hv_pcidev_description func[0];
>> };
>>
>> enum hv_pcichild_state {
>>@@ -527,7 +541,7 @@ struct hv_pci_dev {
>> 	refcount_t refs;
>> 	enum hv_pcichild_state state;
>> 	struct pci_slot *pci_slot;
>>-	struct pci_function_description desc;
>>+	struct hv_pcidev_description desc;
>> 	bool reported_missing;
>> 	struct hv_pcibus_device *hbus;
>> 	struct work_struct wrk;
>>@@ -1862,7 +1876,7 @@ static void q_resource_requirements(void
>>*context, struct pci_response *resp,
>>  * Return: Pointer to the new tracking struct
>>  */
>> static struct hv_pci_dev *new_pcichild_device(struct hv_pcibus_device *hbus,
>>-		struct pci_function_description *desc)
>>+		struct hv_pcidev_description *desc)
>> {
>> 	struct hv_pci_dev *hpdev;
>> 	struct pci_child_message *res_req;
>>@@ -1973,7 +1987,7 @@ static void pci_devices_present_work(struct
>>work_struct *work)  {
>> 	u32 child_no;
>> 	bool found;
>>-	struct pci_function_description *new_desc;
>>+	struct hv_pcidev_description *new_desc;
>> 	struct hv_pci_dev *hpdev;
>> 	struct hv_pcibus_device *hbus;
>> 	struct list_head removed;
>>@@ -2090,43 +2104,26 @@ static void pci_devices_present_work(struct
>>work_struct *work)
>> 	put_hvpcibus(hbus);
>> 	kfree(dr);
>> }
>>-
>> /**
>>- * hv_pci_devices_present() - Handles list of new children
>>+ * hv_pci_start_relations_work() - Queue work to start device
>>+ discovery
>>  * @hbus:	Root PCI bus, as understood by this driver
>>- * @relations:	Packet from host listing children
>>+ * @dr:		The list of children returned from host
>>  *
>>- * This function is invoked whenever a new list of devices for
>>- * this bus appears.
>>+ * Return:  0 on success, -errno on failure
>>  */
>>-static void hv_pci_devices_present(struct hv_pcibus_device *hbus,
>>-				   struct pci_bus_relations *relations)
>>+static int hv_pci_start_relations_work(struct hv_pcibus_device *hbus,
>>+				       struct hv_dr_state *dr)
>> {
>>-	struct hv_dr_state *dr;
>> 	struct hv_dr_work *dr_wrk;
>>-	unsigned long flags;
>> 	bool pending_dr;
>>+	unsigned long flags;
>>
>> 	dr_wrk = kzalloc(sizeof(*dr_wrk), GFP_NOWAIT);
>> 	if (!dr_wrk)
>>-		return;
>>-
>>-	dr = kzalloc(offsetof(struct hv_dr_state, func) +
>>-		     (sizeof(struct pci_function_description) *
>>-		      (relations->device_count)), GFP_NOWAIT);
>>-	if (!dr)  {
>>-		kfree(dr_wrk);
>>-		return;
>>-	}
>>+		return -ENOMEM;
>>
>> 	INIT_WORK(&dr_wrk->wrk, pci_devices_present_work);
>> 	dr_wrk->bus = hbus;
>>-	dr->device_count = relations->device_count;
>>-	if (dr->device_count != 0) {
>>-		memcpy(dr->func, relations->func,
>>-		       sizeof(struct pci_function_description) *
>>-		       dr->device_count);
>>-	}
>>
>> 	spin_lock_irqsave(&hbus->device_list_lock, flags);
>> 	/*
>>@@ -2144,6 +2141,47 @@ static void hv_pci_devices_present(struct
>>hv_pcibus_device *hbus,
>> 		get_hvpcibus(hbus);
>> 		queue_work(hbus->wq, &dr_wrk->wrk);
>> 	}
>>+
>>+	return 0;
>>+}
>>+
>>+/**
>>+ * hv_pci_devices_present() - Handle list of new children
>>+ * @hbus:	Root PCI bus, as understood by this driver
>>+ * @relations:	Packet from host listing children
>>+ *
>>+ * Process a new list of devices on the bus. The list of devices is
>>+ * discovered by VSP and sent to us via VSP message PCI_BUS_RELATIONS,
>>+ * whenever a new list of devices for this bus appears.
>>+ */
>>+static void hv_pci_devices_present(struct hv_pcibus_device *hbus,
>>+				   struct pci_bus_relations *relations) {
>>+	struct hv_dr_state *dr;
>>+	int i;
>>+
>>+	dr = kzalloc(offsetof(struct hv_dr_state, func) +
>>+		     (sizeof(struct hv_pcidev_description) *
>>+		      (relations->device_count)), GFP_NOWAIT);
>>+
>>+	if (!dr)
>>+		return;
>>+
>>+	dr->device_count = relations->device_count;
>>+	for (i = 0; i < dr->device_count; i++) {
>>+		dr->func[i].v_id = relations->func[i].v_id;
>>+		dr->func[i].d_id = relations->func[i].d_id;
>>+		dr->func[i].rev = relations->func[i].rev;
>>+		dr->func[i].prog_intf = relations->func[i].prog_intf;
>>+		dr->func[i].subclass = relations->func[i].subclass;
>>+		dr->func[i].base_class = relations->func[i].base_class;
>>+		dr->func[i].subsystem_id = relations->func[i].subsystem_id;
>>+		dr->func[i].win_slot = relations->func[i].win_slot;
>>+		dr->func[i].ser = relations->func[i].ser;
>>+	}
>>+
>>+	if (hv_pci_start_relations_work(hbus, dr))
>>+		kfree(dr);
>> }
>>
>> /**
>>@@ -3018,7 +3056,7 @@ static void hv_pci_bus_exit(struct hv_device *hdev)
>> 		struct pci_packet teardown_packet;
>> 		u8 buffer[sizeof(struct pci_message)];
>> 	} pkt;
>>-	struct pci_bus_relations relations;
>>+	struct hv_dr_state *dr;
>> 	struct hv_pci_compl comp_pkt;
>> 	int ret;
>>
>>@@ -3030,8 +3068,9 @@ static void hv_pci_bus_exit(struct hv_device *hdev)
>> 		return;
>>
>> 	/* Delete any children which might still exist. */
>>-	memset(&relations, 0, sizeof(relations));
>>-	hv_pci_devices_present(hbus, &relations);
>>+	dr = kzalloc(sizeof(*dr), GFP_KERNEL);
>>+	if (dr && hv_pci_start_relations_work(hbus, dr))
>>+		kfree(dr);
>>
>> 	ret = hv_send_resources_released(hdev);
>> 	if (ret)
>>--
>>2.17.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Patch v4 2/2] PCI: hv: Add support for protocol 1.3 and support PCI_BUS_RELATIONS2
  2020-01-13 20:08 ` [Patch v4 2/2] PCI: hv: Add support for protocol 1.3 and support PCI_BUS_RELATIONS2 longli
@ 2020-02-25 10:36   ` Lorenzo Pieralisi
  2020-02-25 21:28     ` Long Li
  0 siblings, 1 reply; 6+ messages in thread
From: Lorenzo Pieralisi @ 2020-02-25 10:36 UTC (permalink / raw)
  To: longli
  Cc: K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger, Sasha Levin,
	Andrew Murray, Bjorn Helgaas, linux-hyperv, linux-pci,
	linux-kernel, Long Li

On Mon, Jan 13, 2020 at 12:08:21PM -0800, longli@linuxonhyperv.com wrote:
> From: Long Li <longli@microsoft.com>
> 
> Starting with Hyper-V PCI protocol version 1.3, the host VSP can send
> PCI_BUS_RELATIONS2 and pass the vNUMA node information for devices on the
> bus. The vNUMA node tells which guest NUMA node this device is on based
> on guest VM configuration topology and physical device inforamtion.

s/inforamtion/information

Please rebase this series on top of my pci/hv branch, it does
not apply, I will merge it then.

Thanks,
Lorenzo

> Add code to negotiate v1.3 and process PCI_BUS_RELATIONS2.
> 
> Signed-off-by: Long Li <longli@microsoft.com>
> Reviewed-by: Michael Kelley <mikelley@microsoft.com>
> ---
> Changes
> v2: Changed some spaces to tabs, added put_pcichild() after get_pcichild_wslot(), renamed pci_assign_numa_node() to hv_pci_assign_numa_node()
> v4: Fixed spelling
> 
>  drivers/pci/controller/pci-hyperv.c | 109 ++++++++++++++++++++++++++++
>  1 file changed, 109 insertions(+)
> 
> diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
> index 3b3e1967cf08..147358fae8a2 100644
> --- a/drivers/pci/controller/pci-hyperv.c
> +++ b/drivers/pci/controller/pci-hyperv.c
> @@ -63,6 +63,7 @@
>  enum pci_protocol_version_t {
>  	PCI_PROTOCOL_VERSION_1_1 = PCI_MAKE_VERSION(1, 1),	/* Win10 */
>  	PCI_PROTOCOL_VERSION_1_2 = PCI_MAKE_VERSION(1, 2),	/* RS1 */
> +	PCI_PROTOCOL_VERSION_1_3 = PCI_MAKE_VERSION(1, 3),	/* Vibranium */
>  };
>  
>  #define CPU_AFFINITY_ALL	-1ULL
> @@ -72,6 +73,7 @@ enum pci_protocol_version_t {
>   * first.
>   */
>  static enum pci_protocol_version_t pci_protocol_versions[] = {
> +	PCI_PROTOCOL_VERSION_1_3,
>  	PCI_PROTOCOL_VERSION_1_2,
>  	PCI_PROTOCOL_VERSION_1_1,
>  };
> @@ -124,6 +126,7 @@ enum pci_message_type {
>  	PCI_RESOURCES_ASSIGNED2		= PCI_MESSAGE_BASE + 0x16,
>  	PCI_CREATE_INTERRUPT_MESSAGE2	= PCI_MESSAGE_BASE + 0x17,
>  	PCI_DELETE_INTERRUPT_MESSAGE2	= PCI_MESSAGE_BASE + 0x18, /* unused */
> +	PCI_BUS_RELATIONS2		= PCI_MESSAGE_BASE + 0x19,
>  	PCI_MESSAGE_MAXIMUM
>  };
>  
> @@ -169,6 +172,26 @@ struct pci_function_description {
>  	u32	ser;	/* serial number */
>  } __packed;
>  
> +enum pci_device_description_flags {
> +	HV_PCI_DEVICE_FLAG_NONE			= 0x0,
> +	HV_PCI_DEVICE_FLAG_NUMA_AFFINITY	= 0x1,
> +};
> +
> +struct pci_function_description2 {
> +	u16	v_id;	/* vendor ID */
> +	u16	d_id;	/* device ID */
> +	u8	rev;
> +	u8	prog_intf;
> +	u8	subclass;
> +	u8	base_class;
> +	u32	subsystem_id;
> +	union	win_slot_encoding win_slot;
> +	u32	ser;	/* serial number */
> +	u32	flags;
> +	u16	virtual_numa_node;
> +	u16	reserved;
> +} __packed;
> +
>  /**
>   * struct hv_msi_desc
>   * @vector:		IDT entry
> @@ -304,6 +327,12 @@ struct pci_bus_relations {
>  	struct pci_function_description func[0];
>  } __packed;
>  
> +struct pci_bus_relations2 {
> +	struct pci_incoming_message incoming;
> +	u32 device_count;
> +	struct pci_function_description2 func[0];
> +} __packed;
> +
>  struct pci_q_res_req_response {
>  	struct vmpacket_descriptor hdr;
>  	s32 status;			/* negative values are failures */
> @@ -1417,6 +1446,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
>  		break;
>  
>  	case PCI_PROTOCOL_VERSION_1_2:
> +	case PCI_PROTOCOL_VERSION_1_3:
>  		size = hv_compose_msi_req_v2(&ctxt.int_pkts.v2,
>  					dest,
>  					hpdev->desc.win_slot.slot,
> @@ -1798,6 +1828,27 @@ static void hv_pci_remove_slots(struct hv_pcibus_device *hbus)
>  	}
>  }
>  
> +/*
> + * Set NUMA node for the devices on the bus
> + */
> +static void hv_pci_assign_numa_node(struct hv_pcibus_device *hbus)
> +{
> +	struct pci_dev *dev;
> +	struct pci_bus *bus = hbus->pci_bus;
> +	struct hv_pci_dev *hv_dev;
> +
> +	list_for_each_entry(dev, &bus->devices, bus_list) {
> +		hv_dev = get_pcichild_wslot(hbus, devfn_to_wslot(dev->devfn));
> +		if (!hv_dev)
> +			continue;
> +
> +		if (hv_dev->desc.flags & HV_PCI_DEVICE_FLAG_NUMA_AFFINITY)
> +			set_dev_node(&dev->dev, hv_dev->desc.virtual_numa_node);
> +
> +		put_pcichild(hv_dev);
> +	}
> +}
> +
>  /**
>   * create_root_hv_pci_bus() - Expose a new root PCI bus
>   * @hbus:	Root PCI bus, as understood by this driver
> @@ -1820,6 +1871,7 @@ static int create_root_hv_pci_bus(struct hv_pcibus_device *hbus)
>  
>  	pci_lock_rescan_remove();
>  	pci_scan_child_bus(hbus->pci_bus);
> +	hv_pci_assign_numa_node(hbus);
>  	pci_bus_assign_resources(hbus->pci_bus);
>  	hv_pci_assign_slots(hbus);
>  	pci_bus_add_devices(hbus->pci_bus);
> @@ -2088,6 +2140,7 @@ static void pci_devices_present_work(struct work_struct *work)
>  		 */
>  		pci_lock_rescan_remove();
>  		pci_scan_child_bus(hbus->pci_bus);
> +		hv_pci_assign_numa_node(hbus);
>  		hv_pci_assign_slots(hbus);
>  		pci_unlock_rescan_remove();
>  		break;
> @@ -2184,6 +2237,46 @@ static void hv_pci_devices_present(struct hv_pcibus_device *hbus,
>  		kfree(dr);
>  }
>  
> +/**
> + * hv_pci_devices_present2() - Handle list of new children
> + * @hbus:	Root PCI bus, as understood by this driver
> + * @relations2:	Packet from host listing children
> + *
> + * This function is the v2 version of hv_pci_devices_present()
> + */
> +static void hv_pci_devices_present2(struct hv_pcibus_device *hbus,
> +				    struct pci_bus_relations2 *relations)
> +{
> +	struct hv_dr_state *dr;
> +	int i;
> +
> +	dr = kzalloc(offsetof(struct hv_dr_state, func) +
> +		     (sizeof(struct hv_pcidev_description) *
> +		      (relations->device_count)), GFP_NOWAIT);
> +
> +	if (!dr)
> +		return;
> +
> +	dr->device_count = relations->device_count;
> +	for (i = 0; i < dr->device_count; i++) {
> +		dr->func[i].v_id = relations->func[i].v_id;
> +		dr->func[i].d_id = relations->func[i].d_id;
> +		dr->func[i].rev = relations->func[i].rev;
> +		dr->func[i].prog_intf = relations->func[i].prog_intf;
> +		dr->func[i].subclass = relations->func[i].subclass;
> +		dr->func[i].base_class = relations->func[i].base_class;
> +		dr->func[i].subsystem_id = relations->func[i].subsystem_id;
> +		dr->func[i].win_slot = relations->func[i].win_slot;
> +		dr->func[i].ser = relations->func[i].ser;
> +		dr->func[i].flags = relations->func[i].flags;
> +		dr->func[i].virtual_numa_node =
> +			relations->func[i].virtual_numa_node;
> +	}
> +
> +	if (hv_pci_start_relations_work(hbus, dr))
> +		kfree(dr);
> +}
> +
>  /**
>   * hv_eject_device_work() - Asynchronously handles ejection
>   * @work:	Work struct embedded in internal device struct
> @@ -2289,6 +2382,7 @@ static void hv_pci_onchannelcallback(void *context)
>  	struct pci_response *response;
>  	struct pci_incoming_message *new_message;
>  	struct pci_bus_relations *bus_rel;
> +	struct pci_bus_relations2 *bus_rel2;
>  	struct pci_dev_inval_block *inval;
>  	struct pci_dev_incoming *dev_message;
>  	struct hv_pci_dev *hpdev;
> @@ -2356,6 +2450,21 @@ static void hv_pci_onchannelcallback(void *context)
>  				hv_pci_devices_present(hbus, bus_rel);
>  				break;
>  
> +			case PCI_BUS_RELATIONS2:
> +
> +				bus_rel2 = (struct pci_bus_relations2 *)buffer;
> +				if (bytes_recvd <
> +				    offsetof(struct pci_bus_relations2, func) +
> +				    (sizeof(struct pci_function_description2) *
> +				     (bus_rel2->device_count))) {
> +					dev_err(&hbus->hdev->device,
> +						"bus relations v2 too small\n");
> +					break;
> +				}
> +
> +				hv_pci_devices_present2(hbus, bus_rel2);
> +				break;
> +
>  			case PCI_EJECT:
>  
>  				dev_message = (struct pci_dev_incoming *)buffer;
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* RE: [Patch v4 2/2] PCI: hv: Add support for protocol 1.3 and support PCI_BUS_RELATIONS2
  2020-02-25 10:36   ` Lorenzo Pieralisi
@ 2020-02-25 21:28     ` Long Li
  0 siblings, 0 replies; 6+ messages in thread
From: Long Li @ 2020-02-25 21:28 UTC (permalink / raw)
  To: Lorenzo Pieralisi, longli
  Cc: KY Srinivasan, Haiyang Zhang, Stephen Hemminger, Sasha Levin,
	Andrew Murray, Bjorn Helgaas, linux-hyperv, linux-pci,
	linux-kernel

>Subject: Re: [Patch v4 2/2] PCI: hv: Add support for protocol 1.3 and support
>PCI_BUS_RELATIONS2
>
>On Mon, Jan 13, 2020 at 12:08:21PM -0800, longli@linuxonhyperv.com wrote:
>> From: Long Li <longli@microsoft.com>
>>
>> Starting with Hyper-V PCI protocol version 1.3, the host VSP can send
>> PCI_BUS_RELATIONS2 and pass the vNUMA node information for devices
>on
>> the bus. The vNUMA node tells which guest NUMA node this device is on
>> based on guest VM configuration topology and physical device inforamtion.
>
>s/inforamtion/information
>
>Please rebase this series on top of my pci/hv branch, it does not apply, I will
>merge it then.
>
>Thanks,
>Lorenzo

I will send v5.

Thanks,
Long

>
>> Add code to negotiate v1.3 and process PCI_BUS_RELATIONS2.
>>
>> Signed-off-by: Long Li <longli@microsoft.com>
>> Reviewed-by: Michael Kelley <mikelley@microsoft.com>
>> ---
>> Changes
>> v2: Changed some spaces to tabs, added put_pcichild() after
>> get_pcichild_wslot(), renamed pci_assign_numa_node() to
>> hv_pci_assign_numa_node()
>> v4: Fixed spelling
>>
>>  drivers/pci/controller/pci-hyperv.c | 109
>> ++++++++++++++++++++++++++++
>>  1 file changed, 109 insertions(+)
>>
>> diff --git a/drivers/pci/controller/pci-hyperv.c
>> b/drivers/pci/controller/pci-hyperv.c
>> index 3b3e1967cf08..147358fae8a2 100644
>> --- a/drivers/pci/controller/pci-hyperv.c
>> +++ b/drivers/pci/controller/pci-hyperv.c
>> @@ -63,6 +63,7 @@
>>  enum pci_protocol_version_t {
>>  	PCI_PROTOCOL_VERSION_1_1 = PCI_MAKE_VERSION(1, 1),	/*
>Win10 */
>>  	PCI_PROTOCOL_VERSION_1_2 = PCI_MAKE_VERSION(1, 2),	/* RS1
>*/
>> +	PCI_PROTOCOL_VERSION_1_3 = PCI_MAKE_VERSION(1, 3),	/*
>Vibranium */
>>  };
>>
>>  #define CPU_AFFINITY_ALL	-1ULL
>> @@ -72,6 +73,7 @@ enum pci_protocol_version_t {
>>   * first.
>>   */
>>  static enum pci_protocol_version_t pci_protocol_versions[] = {
>> +	PCI_PROTOCOL_VERSION_1_3,
>>  	PCI_PROTOCOL_VERSION_1_2,
>>  	PCI_PROTOCOL_VERSION_1_1,
>>  };
>> @@ -124,6 +126,7 @@ enum pci_message_type {
>>  	PCI_RESOURCES_ASSIGNED2		= PCI_MESSAGE_BASE + 0x16,
>>  	PCI_CREATE_INTERRUPT_MESSAGE2	= PCI_MESSAGE_BASE + 0x17,
>>  	PCI_DELETE_INTERRUPT_MESSAGE2	= PCI_MESSAGE_BASE + 0x18,
>/* unused */
>> +	PCI_BUS_RELATIONS2		= PCI_MESSAGE_BASE + 0x19,
>>  	PCI_MESSAGE_MAXIMUM
>>  };
>>
>> @@ -169,6 +172,26 @@ struct pci_function_description {
>>  	u32	ser;	/* serial number */
>>  } __packed;
>>
>> +enum pci_device_description_flags {
>> +	HV_PCI_DEVICE_FLAG_NONE			= 0x0,
>> +	HV_PCI_DEVICE_FLAG_NUMA_AFFINITY	= 0x1,
>> +};
>> +
>> +struct pci_function_description2 {
>> +	u16	v_id;	/* vendor ID */
>> +	u16	d_id;	/* device ID */
>> +	u8	rev;
>> +	u8	prog_intf;
>> +	u8	subclass;
>> +	u8	base_class;
>> +	u32	subsystem_id;
>> +	union	win_slot_encoding win_slot;
>> +	u32	ser;	/* serial number */
>> +	u32	flags;
>> +	u16	virtual_numa_node;
>> +	u16	reserved;
>> +} __packed;
>> +
>>  /**
>>   * struct hv_msi_desc
>>   * @vector:		IDT entry
>> @@ -304,6 +327,12 @@ struct pci_bus_relations {
>>  	struct pci_function_description func[0];  } __packed;
>>
>> +struct pci_bus_relations2 {
>> +	struct pci_incoming_message incoming;
>> +	u32 device_count;
>> +	struct pci_function_description2 func[0]; } __packed;
>> +
>>  struct pci_q_res_req_response {
>>  	struct vmpacket_descriptor hdr;
>>  	s32 status;			/* negative values are failures */
>> @@ -1417,6 +1446,7 @@ static void hv_compose_msi_msg(struct irq_data
>*data, struct msi_msg *msg)
>>  		break;
>>
>>  	case PCI_PROTOCOL_VERSION_1_2:
>> +	case PCI_PROTOCOL_VERSION_1_3:
>>  		size = hv_compose_msi_req_v2(&ctxt.int_pkts.v2,
>>  					dest,
>>  					hpdev->desc.win_slot.slot,
>> @@ -1798,6 +1828,27 @@ static void hv_pci_remove_slots(struct
>hv_pcibus_device *hbus)
>>  	}
>>  }
>>
>> +/*
>> + * Set NUMA node for the devices on the bus  */ static void
>> +hv_pci_assign_numa_node(struct hv_pcibus_device *hbus) {
>> +	struct pci_dev *dev;
>> +	struct pci_bus *bus = hbus->pci_bus;
>> +	struct hv_pci_dev *hv_dev;
>> +
>> +	list_for_each_entry(dev, &bus->devices, bus_list) {
>> +		hv_dev = get_pcichild_wslot(hbus, devfn_to_wslot(dev-
>>devfn));
>> +		if (!hv_dev)
>> +			continue;
>> +
>> +		if (hv_dev->desc.flags &
>HV_PCI_DEVICE_FLAG_NUMA_AFFINITY)
>> +			set_dev_node(&dev->dev, hv_dev-
>>desc.virtual_numa_node);
>> +
>> +		put_pcichild(hv_dev);
>> +	}
>> +}
>> +
>>  /**
>>   * create_root_hv_pci_bus() - Expose a new root PCI bus
>>   * @hbus:	Root PCI bus, as understood by this driver
>> @@ -1820,6 +1871,7 @@ static int create_root_hv_pci_bus(struct
>> hv_pcibus_device *hbus)
>>
>>  	pci_lock_rescan_remove();
>>  	pci_scan_child_bus(hbus->pci_bus);
>> +	hv_pci_assign_numa_node(hbus);
>>  	pci_bus_assign_resources(hbus->pci_bus);
>>  	hv_pci_assign_slots(hbus);
>>  	pci_bus_add_devices(hbus->pci_bus);
>> @@ -2088,6 +2140,7 @@ static void pci_devices_present_work(struct
>work_struct *work)
>>  		 */
>>  		pci_lock_rescan_remove();
>>  		pci_scan_child_bus(hbus->pci_bus);
>> +		hv_pci_assign_numa_node(hbus);
>>  		hv_pci_assign_slots(hbus);
>>  		pci_unlock_rescan_remove();
>>  		break;
>> @@ -2184,6 +2237,46 @@ static void hv_pci_devices_present(struct
>hv_pcibus_device *hbus,
>>  		kfree(dr);
>>  }
>>
>> +/**
>> + * hv_pci_devices_present2() - Handle list of new children
>> + * @hbus:	Root PCI bus, as understood by this driver
>> + * @relations2:	Packet from host listing children
>> + *
>> + * This function is the v2 version of hv_pci_devices_present()  */
>> +static void hv_pci_devices_present2(struct hv_pcibus_device *hbus,
>> +				    struct pci_bus_relations2 *relations) {
>> +	struct hv_dr_state *dr;
>> +	int i;
>> +
>> +	dr = kzalloc(offsetof(struct hv_dr_state, func) +
>> +		     (sizeof(struct hv_pcidev_description) *
>> +		      (relations->device_count)), GFP_NOWAIT);
>> +
>> +	if (!dr)
>> +		return;
>> +
>> +	dr->device_count = relations->device_count;
>> +	for (i = 0; i < dr->device_count; i++) {
>> +		dr->func[i].v_id = relations->func[i].v_id;
>> +		dr->func[i].d_id = relations->func[i].d_id;
>> +		dr->func[i].rev = relations->func[i].rev;
>> +		dr->func[i].prog_intf = relations->func[i].prog_intf;
>> +		dr->func[i].subclass = relations->func[i].subclass;
>> +		dr->func[i].base_class = relations->func[i].base_class;
>> +		dr->func[i].subsystem_id = relations->func[i].subsystem_id;
>> +		dr->func[i].win_slot = relations->func[i].win_slot;
>> +		dr->func[i].ser = relations->func[i].ser;
>> +		dr->func[i].flags = relations->func[i].flags;
>> +		dr->func[i].virtual_numa_node =
>> +			relations->func[i].virtual_numa_node;
>> +	}
>> +
>> +	if (hv_pci_start_relations_work(hbus, dr))
>> +		kfree(dr);
>> +}
>> +
>>  /**
>>   * hv_eject_device_work() - Asynchronously handles ejection
>>   * @work:	Work struct embedded in internal device struct
>> @@ -2289,6 +2382,7 @@ static void hv_pci_onchannelcallback(void
>*context)
>>  	struct pci_response *response;
>>  	struct pci_incoming_message *new_message;
>>  	struct pci_bus_relations *bus_rel;
>> +	struct pci_bus_relations2 *bus_rel2;
>>  	struct pci_dev_inval_block *inval;
>>  	struct pci_dev_incoming *dev_message;
>>  	struct hv_pci_dev *hpdev;
>> @@ -2356,6 +2450,21 @@ static void hv_pci_onchannelcallback(void
>*context)
>>  				hv_pci_devices_present(hbus, bus_rel);
>>  				break;
>>
>> +			case PCI_BUS_RELATIONS2:
>> +
>> +				bus_rel2 = (struct pci_bus_relations2 *)buffer;
>> +				if (bytes_recvd <
>> +				    offsetof(struct pci_bus_relations2, func) +
>> +				    (sizeof(struct pci_function_description2) *
>> +				     (bus_rel2->device_count))) {
>> +					dev_err(&hbus->hdev->device,
>> +						"bus relations v2 too small\n");
>> +					break;
>> +				}
>> +
>> +				hv_pci_devices_present2(hbus, bus_rel2);
>> +				break;
>> +
>>  			case PCI_EJECT:
>>
>>  				dev_message = (struct pci_dev_incoming
>*)buffer;
>> --
>> 2.17.1
>>

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-02-25 21:28 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-13 20:08 [Patch v4 1/2] PCI: hv: Decouple the func definition in hv_dr_state from VSP message longli
2020-01-13 20:08 ` [Patch v4 2/2] PCI: hv: Add support for protocol 1.3 and support PCI_BUS_RELATIONS2 longli
2020-02-25 10:36   ` Lorenzo Pieralisi
2020-02-25 21:28     ` Long Li
2020-01-22 21:42 ` [Patch v4 1/2] PCI: hv: Decouple the func definition in hv_dr_state from VSP message Long Li
2020-02-06 23:48   ` Long Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).