RE: [Patch v4 2/2] PCI: hv: Add support for protocol 1.3 and support PCI_BUS_RELATIONS2

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>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@xxxxxxxxxxxxxxxxx wrote:
>> From: Long Li <longli@xxxxxxxxxxxxx>
>>
>> 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@xxxxxxxxxxxxx>
>> Reviewed-by: Michael Kelley <mikelley@xxxxxxxxxxxxx>
>> ---
>> 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
>>




[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux