Message ID | 1578946101-74036-2-git-send-email-longli@linuxonhyperv.com (mailing list archive) |
---|---|
State | Superseded, archived |
Delegated to: | Lorenzo Pieralisi |
Headers | show |
Series | [v4,1/2] PCI: hv: Decouple the func definition in hv_dr_state from VSP message | expand |
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 >
>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 >>
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;