diff options
Diffstat (limited to 'drivers/pci/host/pci-hyperv.c')
-rw-r--r-- | drivers/pci/host/pci-hyperv.c | 445 |
1 files changed, 364 insertions, 81 deletions
diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c index 84936383e269..415dcc69a502 100644 --- a/drivers/pci/host/pci-hyperv.c +++ b/drivers/pci/host/pci-hyperv.c | |||
@@ -64,22 +64,39 @@ | |||
64 | * major version. | 64 | * major version. |
65 | */ | 65 | */ |
66 | 66 | ||
67 | #define PCI_MAKE_VERSION(major, minor) ((u32)(((major) << 16) | (major))) | 67 | #define PCI_MAKE_VERSION(major, minor) ((u32)(((major) << 16) | (minor))) |
68 | #define PCI_MAJOR_VERSION(version) ((u32)(version) >> 16) | 68 | #define PCI_MAJOR_VERSION(version) ((u32)(version) >> 16) |
69 | #define PCI_MINOR_VERSION(version) ((u32)(version) & 0xff) | 69 | #define PCI_MINOR_VERSION(version) ((u32)(version) & 0xff) |
70 | 70 | ||
71 | enum { | 71 | enum pci_protocol_version_t { |
72 | PCI_PROTOCOL_VERSION_1_1 = PCI_MAKE_VERSION(1, 1), | 72 | PCI_PROTOCOL_VERSION_1_1 = PCI_MAKE_VERSION(1, 1), /* Win10 */ |
73 | PCI_PROTOCOL_VERSION_CURRENT = PCI_PROTOCOL_VERSION_1_1 | 73 | PCI_PROTOCOL_VERSION_1_2 = PCI_MAKE_VERSION(1, 2), /* RS1 */ |
74 | }; | 74 | }; |
75 | 75 | ||
76 | #define CPU_AFFINITY_ALL -1ULL | 76 | #define CPU_AFFINITY_ALL -1ULL |
77 | |||
78 | /* | ||
79 | * Supported protocol versions in the order of probing - highest go | ||
80 | * first. | ||
81 | */ | ||
82 | static enum pci_protocol_version_t pci_protocol_versions[] = { | ||
83 | PCI_PROTOCOL_VERSION_1_2, | ||
84 | PCI_PROTOCOL_VERSION_1_1, | ||
85 | }; | ||
86 | |||
87 | /* | ||
88 | * Protocol version negotiated by hv_pci_protocol_negotiation(). | ||
89 | */ | ||
90 | static enum pci_protocol_version_t pci_protocol_version; | ||
91 | |||
77 | #define PCI_CONFIG_MMIO_LENGTH 0x2000 | 92 | #define PCI_CONFIG_MMIO_LENGTH 0x2000 |
78 | #define CFG_PAGE_OFFSET 0x1000 | 93 | #define CFG_PAGE_OFFSET 0x1000 |
79 | #define CFG_PAGE_SIZE (PCI_CONFIG_MMIO_LENGTH - CFG_PAGE_OFFSET) | 94 | #define CFG_PAGE_SIZE (PCI_CONFIG_MMIO_LENGTH - CFG_PAGE_OFFSET) |
80 | 95 | ||
81 | #define MAX_SUPPORTED_MSI_MESSAGES 0x400 | 96 | #define MAX_SUPPORTED_MSI_MESSAGES 0x400 |
82 | 97 | ||
98 | #define STATUS_REVISION_MISMATCH 0xC0000059 | ||
99 | |||
83 | /* | 100 | /* |
84 | * Message Types | 101 | * Message Types |
85 | */ | 102 | */ |
@@ -109,6 +126,9 @@ enum pci_message_type { | |||
109 | PCI_QUERY_PROTOCOL_VERSION = PCI_MESSAGE_BASE + 0x13, | 126 | PCI_QUERY_PROTOCOL_VERSION = PCI_MESSAGE_BASE + 0x13, |
110 | PCI_CREATE_INTERRUPT_MESSAGE = PCI_MESSAGE_BASE + 0x14, | 127 | PCI_CREATE_INTERRUPT_MESSAGE = PCI_MESSAGE_BASE + 0x14, |
111 | PCI_DELETE_INTERRUPT_MESSAGE = PCI_MESSAGE_BASE + 0x15, | 128 | PCI_DELETE_INTERRUPT_MESSAGE = PCI_MESSAGE_BASE + 0x15, |
129 | PCI_RESOURCES_ASSIGNED2 = PCI_MESSAGE_BASE + 0x16, | ||
130 | PCI_CREATE_INTERRUPT_MESSAGE2 = PCI_MESSAGE_BASE + 0x17, | ||
131 | PCI_DELETE_INTERRUPT_MESSAGE2 = PCI_MESSAGE_BASE + 0x18, /* unused */ | ||
112 | PCI_MESSAGE_MAXIMUM | 132 | PCI_MESSAGE_MAXIMUM |
113 | }; | 133 | }; |
114 | 134 | ||
@@ -179,6 +199,30 @@ struct hv_msi_desc { | |||
179 | } __packed; | 199 | } __packed; |
180 | 200 | ||
181 | /** | 201 | /** |
202 | * struct hv_msi_desc2 - 1.2 version of hv_msi_desc | ||
203 | * @vector: IDT entry | ||
204 | * @delivery_mode: As defined in Intel's Programmer's | ||
205 | * Reference Manual, Volume 3, Chapter 8. | ||
206 | * @vector_count: Number of contiguous entries in the | ||
207 | * Interrupt Descriptor Table that are | ||
208 | * occupied by this Message-Signaled | ||
209 | * Interrupt. For "MSI", as first defined | ||
210 | * in PCI 2.2, this can be between 1 and | ||
211 | * 32. For "MSI-X," as first defined in PCI | ||
212 | * 3.0, this must be 1, as each MSI-X table | ||
213 | * entry would have its own descriptor. | ||
214 | * @processor_count: number of bits enabled in array. | ||
215 | * @processor_array: All the target virtual processors. | ||
216 | */ | ||
217 | struct hv_msi_desc2 { | ||
218 | u8 vector; | ||
219 | u8 delivery_mode; | ||
220 | u16 vector_count; | ||
221 | u16 processor_count; | ||
222 | u16 processor_array[32]; | ||
223 | } __packed; | ||
224 | |||
225 | /** | ||
182 | * struct tran_int_desc | 226 | * struct tran_int_desc |
183 | * @reserved: unused, padding | 227 | * @reserved: unused, padding |
184 | * @vector_count: same as in hv_msi_desc | 228 | * @vector_count: same as in hv_msi_desc |
@@ -245,7 +289,7 @@ struct pci_packet { | |||
245 | 289 | ||
246 | struct pci_version_request { | 290 | struct pci_version_request { |
247 | struct pci_message message_type; | 291 | struct pci_message message_type; |
248 | enum pci_message_type protocol_version; | 292 | u32 protocol_version; |
249 | } __packed; | 293 | } __packed; |
250 | 294 | ||
251 | /* | 295 | /* |
@@ -294,6 +338,14 @@ struct pci_resources_assigned { | |||
294 | u32 reserved[4]; | 338 | u32 reserved[4]; |
295 | } __packed; | 339 | } __packed; |
296 | 340 | ||
341 | struct pci_resources_assigned2 { | ||
342 | struct pci_message message_type; | ||
343 | union win_slot_encoding wslot; | ||
344 | u8 memory_range[0x14][6]; /* not used here */ | ||
345 | u32 msi_descriptor_count; | ||
346 | u8 reserved[70]; | ||
347 | } __packed; | ||
348 | |||
297 | struct pci_create_interrupt { | 349 | struct pci_create_interrupt { |
298 | struct pci_message message_type; | 350 | struct pci_message message_type; |
299 | union win_slot_encoding wslot; | 351 | union win_slot_encoding wslot; |
@@ -306,6 +358,12 @@ struct pci_create_int_response { | |||
306 | struct tran_int_desc int_desc; | 358 | struct tran_int_desc int_desc; |
307 | } __packed; | 359 | } __packed; |
308 | 360 | ||
361 | struct pci_create_interrupt2 { | ||
362 | struct pci_message message_type; | ||
363 | union win_slot_encoding wslot; | ||
364 | struct hv_msi_desc2 int_desc; | ||
365 | } __packed; | ||
366 | |||
309 | struct pci_delete_interrupt { | 367 | struct pci_delete_interrupt { |
310 | struct pci_message message_type; | 368 | struct pci_message message_type; |
311 | union win_slot_encoding wslot; | 369 | union win_slot_encoding wslot; |
@@ -331,17 +389,42 @@ static int pci_ring_size = (4 * PAGE_SIZE); | |||
331 | #define HV_PARTITION_ID_SELF ((u64)-1) | 389 | #define HV_PARTITION_ID_SELF ((u64)-1) |
332 | #define HVCALL_RETARGET_INTERRUPT 0x7e | 390 | #define HVCALL_RETARGET_INTERRUPT 0x7e |
333 | 391 | ||
334 | struct retarget_msi_interrupt { | 392 | struct hv_interrupt_entry { |
335 | u64 partition_id; /* use "self" */ | ||
336 | u64 device_id; | ||
337 | u32 source; /* 1 for MSI(-X) */ | 393 | u32 source; /* 1 for MSI(-X) */ |
338 | u32 reserved1; | 394 | u32 reserved1; |
339 | u32 address; | 395 | u32 address; |
340 | u32 data; | 396 | u32 data; |
341 | u64 reserved2; | 397 | }; |
398 | |||
399 | #define HV_VP_SET_BANK_COUNT_MAX 5 /* current implementation limit */ | ||
400 | |||
401 | struct hv_vp_set { | ||
402 | u64 format; /* 0 (HvGenericSetSparse4k) */ | ||
403 | u64 valid_banks; | ||
404 | u64 masks[HV_VP_SET_BANK_COUNT_MAX]; | ||
405 | }; | ||
406 | |||
407 | /* | ||
408 | * flags for hv_device_interrupt_target.flags | ||
409 | */ | ||
410 | #define HV_DEVICE_INTERRUPT_TARGET_MULTICAST 1 | ||
411 | #define HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET 2 | ||
412 | |||
413 | struct hv_device_interrupt_target { | ||
342 | u32 vector; | 414 | u32 vector; |
343 | u32 flags; | 415 | u32 flags; |
344 | u64 vp_mask; | 416 | union { |
417 | u64 vp_mask; | ||
418 | struct hv_vp_set vp_set; | ||
419 | }; | ||
420 | }; | ||
421 | |||
422 | struct retarget_msi_interrupt { | ||
423 | u64 partition_id; /* use "self" */ | ||
424 | u64 device_id; | ||
425 | struct hv_interrupt_entry int_entry; | ||
426 | u64 reserved2; | ||
427 | struct hv_device_interrupt_target int_target; | ||
345 | } __packed; | 428 | } __packed; |
346 | 429 | ||
347 | /* | 430 | /* |
@@ -382,7 +465,10 @@ struct hv_pcibus_device { | |||
382 | struct msi_domain_info msi_info; | 465 | struct msi_domain_info msi_info; |
383 | struct msi_controller msi_chip; | 466 | struct msi_controller msi_chip; |
384 | struct irq_domain *irq_domain; | 467 | struct irq_domain *irq_domain; |
468 | |||
469 | /* hypercall arg, must not cross page boundary */ | ||
385 | struct retarget_msi_interrupt retarget_msi_interrupt_params; | 470 | struct retarget_msi_interrupt retarget_msi_interrupt_params; |
471 | |||
386 | spinlock_t retarget_msi_interrupt_lock; | 472 | spinlock_t retarget_msi_interrupt_lock; |
387 | }; | 473 | }; |
388 | 474 | ||
@@ -476,6 +562,52 @@ static void put_pcichild(struct hv_pci_dev *hv_pcidev, | |||
476 | static void get_hvpcibus(struct hv_pcibus_device *hv_pcibus); | 562 | static void get_hvpcibus(struct hv_pcibus_device *hv_pcibus); |
477 | static void put_hvpcibus(struct hv_pcibus_device *hv_pcibus); | 563 | static void put_hvpcibus(struct hv_pcibus_device *hv_pcibus); |
478 | 564 | ||
565 | |||
566 | /* | ||
567 | * Temporary CPU to vCPU mapping to address transitioning | ||
568 | * vmbus_cpu_number_to_vp_number() being migrated to | ||
569 | * hv_cpu_number_to_vp_number() in a separate patch. Once that patch | ||
570 | * has been picked up in the main line, remove this code here and use | ||
571 | * the official code. | ||
572 | */ | ||
573 | static struct hv_tmpcpumap | ||
574 | { | ||
575 | bool initialized; | ||
576 | u32 vp_index[NR_CPUS]; | ||
577 | } hv_tmpcpumap; | ||
578 | |||
579 | static void hv_tmpcpumap_init_cpu(void *_unused) | ||
580 | { | ||
581 | int cpu = smp_processor_id(); | ||
582 | u64 vp_index; | ||
583 | |||
584 | hv_get_vp_index(vp_index); | ||
585 | |||
586 | hv_tmpcpumap.vp_index[cpu] = vp_index; | ||
587 | } | ||
588 | |||
589 | static void hv_tmpcpumap_init(void) | ||
590 | { | ||
591 | if (hv_tmpcpumap.initialized) | ||
592 | return; | ||
593 | |||
594 | memset(hv_tmpcpumap.vp_index, -1, sizeof(hv_tmpcpumap.vp_index)); | ||
595 | on_each_cpu(hv_tmpcpumap_init_cpu, NULL, true); | ||
596 | hv_tmpcpumap.initialized = true; | ||
597 | } | ||
598 | |||
599 | /** | ||
600 | * hv_tmp_cpu_nr_to_vp_nr() - Convert Linux CPU nr to Hyper-V vCPU nr | ||
601 | * | ||
602 | * Remove once vmbus_cpu_number_to_vp_number() has been converted to | ||
603 | * hv_cpu_number_to_vp_number() and replace callers appropriately. | ||
604 | */ | ||
605 | static u32 hv_tmp_cpu_nr_to_vp_nr(int cpu) | ||
606 | { | ||
607 | return hv_tmpcpumap.vp_index[cpu]; | ||
608 | } | ||
609 | |||
610 | |||
479 | /** | 611 | /** |
480 | * devfn_to_wslot() - Convert from Linux PCI slot to Windows | 612 | * devfn_to_wslot() - Convert from Linux PCI slot to Windows |
481 | * @devfn: The Linux representation of PCI slot | 613 | * @devfn: The Linux representation of PCI slot |
@@ -786,8 +918,11 @@ static void hv_irq_unmask(struct irq_data *data) | |||
786 | struct cpumask *dest; | 918 | struct cpumask *dest; |
787 | struct pci_bus *pbus; | 919 | struct pci_bus *pbus; |
788 | struct pci_dev *pdev; | 920 | struct pci_dev *pdev; |
789 | int cpu; | ||
790 | unsigned long flags; | 921 | unsigned long flags; |
922 | u32 var_size = 0; | ||
923 | int cpu_vmbus; | ||
924 | int cpu; | ||
925 | u64 res; | ||
791 | 926 | ||
792 | dest = irq_data_get_affinity_mask(data); | 927 | dest = irq_data_get_affinity_mask(data); |
793 | pdev = msi_desc_to_pci_dev(msi_desc); | 928 | pdev = msi_desc_to_pci_dev(msi_desc); |
@@ -799,23 +934,74 @@ static void hv_irq_unmask(struct irq_data *data) | |||
799 | params = &hbus->retarget_msi_interrupt_params; | 934 | params = &hbus->retarget_msi_interrupt_params; |
800 | memset(params, 0, sizeof(*params)); | 935 | memset(params, 0, sizeof(*params)); |
801 | params->partition_id = HV_PARTITION_ID_SELF; | 936 | params->partition_id = HV_PARTITION_ID_SELF; |
802 | params->source = 1; /* MSI(-X) */ | 937 | params->int_entry.source = 1; /* MSI(-X) */ |
803 | params->address = msi_desc->msg.address_lo; | 938 | params->int_entry.address = msi_desc->msg.address_lo; |
804 | params->data = msi_desc->msg.data; | 939 | params->int_entry.data = msi_desc->msg.data; |
805 | params->device_id = (hbus->hdev->dev_instance.b[5] << 24) | | 940 | params->device_id = (hbus->hdev->dev_instance.b[5] << 24) | |
806 | (hbus->hdev->dev_instance.b[4] << 16) | | 941 | (hbus->hdev->dev_instance.b[4] << 16) | |
807 | (hbus->hdev->dev_instance.b[7] << 8) | | 942 | (hbus->hdev->dev_instance.b[7] << 8) | |
808 | (hbus->hdev->dev_instance.b[6] & 0xf8) | | 943 | (hbus->hdev->dev_instance.b[6] & 0xf8) | |
809 | PCI_FUNC(pdev->devfn); | 944 | PCI_FUNC(pdev->devfn); |
810 | params->vector = cfg->vector; | 945 | params->int_target.vector = cfg->vector; |
946 | |||
947 | /* | ||
948 | * Honoring apic->irq_delivery_mode set to dest_Fixed by | ||
949 | * setting the HV_DEVICE_INTERRUPT_TARGET_MULTICAST flag results in a | ||
950 | * spurious interrupt storm. Not doing so does not seem to have a | ||
951 | * negative effect (yet?). | ||
952 | */ | ||
953 | |||
954 | if (pci_protocol_version >= PCI_PROTOCOL_VERSION_1_2) { | ||
955 | /* | ||
956 | * PCI_PROTOCOL_VERSION_1_2 supports the VP_SET version of the | ||
957 | * HVCALL_RETARGET_INTERRUPT hypercall, which also coincides | ||
958 | * with >64 VP support. | ||
959 | * ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED | ||
960 | * is not sufficient for this hypercall. | ||
961 | */ | ||
962 | params->int_target.flags |= | ||
963 | HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET; | ||
964 | params->int_target.vp_set.valid_banks = | ||
965 | (1ull << HV_VP_SET_BANK_COUNT_MAX) - 1; | ||
966 | |||
967 | /* | ||
968 | * var-sized hypercall, var-size starts after vp_mask (thus | ||
969 | * vp_set.format does not count, but vp_set.valid_banks does). | ||
970 | */ | ||
971 | var_size = 1 + HV_VP_SET_BANK_COUNT_MAX; | ||
811 | 972 | ||
812 | for_each_cpu_and(cpu, dest, cpu_online_mask) | 973 | for_each_cpu_and(cpu, dest, cpu_online_mask) { |
813 | params->vp_mask |= (1ULL << vmbus_cpu_number_to_vp_number(cpu)); | 974 | cpu_vmbus = hv_tmp_cpu_nr_to_vp_nr(cpu); |
814 | 975 | ||
815 | hv_do_hypercall(HVCALL_RETARGET_INTERRUPT, params, NULL); | 976 | if (cpu_vmbus >= HV_VP_SET_BANK_COUNT_MAX * 64) { |
977 | dev_err(&hbus->hdev->device, | ||
978 | "too high CPU %d", cpu_vmbus); | ||
979 | res = 1; | ||
980 | goto exit_unlock; | ||
981 | } | ||
816 | 982 | ||
983 | params->int_target.vp_set.masks[cpu_vmbus / 64] |= | ||
984 | (1ULL << (cpu_vmbus & 63)); | ||
985 | } | ||
986 | } else { | ||
987 | for_each_cpu_and(cpu, dest, cpu_online_mask) { | ||
988 | params->int_target.vp_mask |= | ||
989 | (1ULL << hv_tmp_cpu_nr_to_vp_nr(cpu)); | ||
990 | } | ||
991 | } | ||
992 | |||
993 | res = hv_do_hypercall(HVCALL_RETARGET_INTERRUPT | (var_size << 17), | ||
994 | params, NULL); | ||
995 | |||
996 | exit_unlock: | ||
817 | spin_unlock_irqrestore(&hbus->retarget_msi_interrupt_lock, flags); | 997 | spin_unlock_irqrestore(&hbus->retarget_msi_interrupt_lock, flags); |
818 | 998 | ||
999 | if (res) { | ||
1000 | dev_err(&hbus->hdev->device, | ||
1001 | "%s() failed: %#llx", __func__, res); | ||
1002 | return; | ||
1003 | } | ||
1004 | |||
819 | pci_msi_unmask_irq(data); | 1005 | pci_msi_unmask_irq(data); |
820 | } | 1006 | } |
821 | 1007 | ||
@@ -836,6 +1022,53 @@ static void hv_pci_compose_compl(void *context, struct pci_response *resp, | |||
836 | complete(&comp_pkt->comp_pkt.host_event); | 1022 | complete(&comp_pkt->comp_pkt.host_event); |
837 | } | 1023 | } |
838 | 1024 | ||
1025 | static u32 hv_compose_msi_req_v1( | ||
1026 | struct pci_create_interrupt *int_pkt, struct cpumask *affinity, | ||
1027 | u32 slot, u8 vector) | ||
1028 | { | ||
1029 | int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE; | ||
1030 | int_pkt->wslot.slot = slot; | ||
1031 | int_pkt->int_desc.vector = vector; | ||
1032 | int_pkt->int_desc.vector_count = 1; | ||
1033 | int_pkt->int_desc.delivery_mode = | ||
1034 | (apic->irq_delivery_mode == dest_LowestPrio) ? | ||
1035 | dest_LowestPrio : dest_Fixed; | ||
1036 | |||
1037 | /* | ||
1038 | * Create MSI w/ dummy vCPU set, overwritten by subsequent retarget in | ||
1039 | * hv_irq_unmask(). | ||
1040 | */ | ||
1041 | int_pkt->int_desc.cpu_mask = CPU_AFFINITY_ALL; | ||
1042 | |||
1043 | return sizeof(*int_pkt); | ||
1044 | } | ||
1045 | |||
1046 | static u32 hv_compose_msi_req_v2( | ||
1047 | struct pci_create_interrupt2 *int_pkt, struct cpumask *affinity, | ||
1048 | u32 slot, u8 vector) | ||
1049 | { | ||
1050 | int cpu; | ||
1051 | |||
1052 | int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE2; | ||
1053 | int_pkt->wslot.slot = slot; | ||
1054 | int_pkt->int_desc.vector = vector; | ||
1055 | int_pkt->int_desc.vector_count = 1; | ||
1056 | int_pkt->int_desc.delivery_mode = | ||
1057 | (apic->irq_delivery_mode == dest_LowestPrio) ? | ||
1058 | dest_LowestPrio : dest_Fixed; | ||
1059 | |||
1060 | /* | ||
1061 | * Create MSI w/ dummy vCPU set targeting just one vCPU, overwritten | ||
1062 | * by subsequent retarget in hv_irq_unmask(). | ||
1063 | */ | ||
1064 | cpu = cpumask_first_and(affinity, cpu_online_mask); | ||
1065 | int_pkt->int_desc.processor_array[0] = | ||
1066 | hv_tmp_cpu_nr_to_vp_nr(cpu); | ||
1067 | int_pkt->int_desc.processor_count = 1; | ||
1068 | |||
1069 | return sizeof(*int_pkt); | ||
1070 | } | ||
1071 | |||
839 | /** | 1072 | /** |
840 | * hv_compose_msi_msg() - Supplies a valid MSI address/data | 1073 | * hv_compose_msi_msg() - Supplies a valid MSI address/data |
841 | * @data: Everything about this MSI | 1074 | * @data: Everything about this MSI |
@@ -854,15 +1087,17 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) | |||
854 | struct hv_pci_dev *hpdev; | 1087 | struct hv_pci_dev *hpdev; |
855 | struct pci_bus *pbus; | 1088 | struct pci_bus *pbus; |
856 | struct pci_dev *pdev; | 1089 | struct pci_dev *pdev; |
857 | struct pci_create_interrupt *int_pkt; | ||
858 | struct compose_comp_ctxt comp; | 1090 | struct compose_comp_ctxt comp; |
859 | struct tran_int_desc *int_desc; | 1091 | struct tran_int_desc *int_desc; |
860 | struct cpumask *affinity; | ||
861 | struct { | 1092 | struct { |
862 | struct pci_packet pkt; | 1093 | struct pci_packet pci_pkt; |
863 | u8 buffer[sizeof(struct pci_create_interrupt)]; | 1094 | union { |
864 | } ctxt; | 1095 | struct pci_create_interrupt v1; |
865 | int cpu; | 1096 | struct pci_create_interrupt2 v2; |
1097 | } int_pkts; | ||
1098 | } __packed ctxt; | ||
1099 | |||
1100 | u32 size; | ||
866 | int ret; | 1101 | int ret; |
867 | 1102 | ||
868 | pdev = msi_desc_to_pci_dev(irq_data_get_msi_desc(data)); | 1103 | pdev = msi_desc_to_pci_dev(irq_data_get_msi_desc(data)); |
@@ -885,36 +1120,44 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) | |||
885 | 1120 | ||
886 | memset(&ctxt, 0, sizeof(ctxt)); | 1121 | memset(&ctxt, 0, sizeof(ctxt)); |
887 | init_completion(&comp.comp_pkt.host_event); | 1122 | init_completion(&comp.comp_pkt.host_event); |
888 | ctxt.pkt.completion_func = hv_pci_compose_compl; | 1123 | ctxt.pci_pkt.completion_func = hv_pci_compose_compl; |
889 | ctxt.pkt.compl_ctxt = ∁ | 1124 | ctxt.pci_pkt.compl_ctxt = ∁ |
890 | int_pkt = (struct pci_create_interrupt *)&ctxt.pkt.message; | 1125 | |
891 | int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE; | 1126 | switch (pci_protocol_version) { |
892 | int_pkt->wslot.slot = hpdev->desc.win_slot.slot; | 1127 | case PCI_PROTOCOL_VERSION_1_1: |
893 | int_pkt->int_desc.vector = cfg->vector; | 1128 | size = hv_compose_msi_req_v1(&ctxt.int_pkts.v1, |
894 | int_pkt->int_desc.vector_count = 1; | 1129 | irq_data_get_affinity_mask(data), |
895 | int_pkt->int_desc.delivery_mode = | 1130 | hpdev->desc.win_slot.slot, |
896 | (apic->irq_delivery_mode == dest_LowestPrio) ? 1 : 0; | 1131 | cfg->vector); |
1132 | break; | ||
897 | 1133 | ||
898 | /* | 1134 | case PCI_PROTOCOL_VERSION_1_2: |
899 | * This bit doesn't have to work on machines with more than 64 | 1135 | size = hv_compose_msi_req_v2(&ctxt.int_pkts.v2, |
900 | * processors because Hyper-V only supports 64 in a guest. | 1136 | irq_data_get_affinity_mask(data), |
901 | */ | 1137 | hpdev->desc.win_slot.slot, |
902 | affinity = irq_data_get_affinity_mask(data); | 1138 | cfg->vector); |
903 | if (cpumask_weight(affinity) >= 32) { | 1139 | break; |
904 | int_pkt->int_desc.cpu_mask = CPU_AFFINITY_ALL; | 1140 | |
905 | } else { | 1141 | default: |
906 | for_each_cpu_and(cpu, affinity, cpu_online_mask) { | 1142 | /* As we only negotiate protocol versions known to this driver, |
907 | int_pkt->int_desc.cpu_mask |= | 1143 | * this path should never hit. However, this is it not a hot |
908 | (1ULL << vmbus_cpu_number_to_vp_number(cpu)); | 1144 | * path so we print a message to aid future updates. |
909 | } | 1145 | */ |
1146 | dev_err(&hbus->hdev->device, | ||
1147 | "Unexpected vPCI protocol, update driver."); | ||
1148 | goto free_int_desc; | ||
910 | } | 1149 | } |
911 | 1150 | ||
912 | ret = vmbus_sendpacket(hpdev->hbus->hdev->channel, int_pkt, | 1151 | ret = vmbus_sendpacket(hpdev->hbus->hdev->channel, &ctxt.int_pkts, |
913 | sizeof(*int_pkt), (unsigned long)&ctxt.pkt, | 1152 | size, (unsigned long)&ctxt.pci_pkt, |
914 | VM_PKT_DATA_INBAND, | 1153 | VM_PKT_DATA_INBAND, |
915 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | 1154 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); |
916 | if (ret) | 1155 | if (ret) { |
1156 | dev_err(&hbus->hdev->device, | ||
1157 | "Sending request for interrupt failed: 0x%x", | ||
1158 | comp.comp_pkt.completion_status); | ||
917 | goto free_int_desc; | 1159 | goto free_int_desc; |
1160 | } | ||
918 | 1161 | ||
919 | wait_for_completion(&comp.comp_pkt.host_event); | 1162 | wait_for_completion(&comp.comp_pkt.host_event); |
920 | 1163 | ||
@@ -1513,12 +1756,12 @@ static void pci_devices_present_work(struct work_struct *work) | |||
1513 | put_pcichild(hpdev, hv_pcidev_ref_initial); | 1756 | put_pcichild(hpdev, hv_pcidev_ref_initial); |
1514 | } | 1757 | } |
1515 | 1758 | ||
1516 | switch(hbus->state) { | 1759 | switch (hbus->state) { |
1517 | case hv_pcibus_installed: | 1760 | case hv_pcibus_installed: |
1518 | /* | 1761 | /* |
1519 | * Tell the core to rescan bus | 1762 | * Tell the core to rescan bus |
1520 | * because there may have been changes. | 1763 | * because there may have been changes. |
1521 | */ | 1764 | */ |
1522 | pci_lock_rescan_remove(); | 1765 | pci_lock_rescan_remove(); |
1523 | pci_scan_child_bus(hbus->pci_bus); | 1766 | pci_scan_child_bus(hbus->pci_bus); |
1524 | pci_unlock_rescan_remove(); | 1767 | pci_unlock_rescan_remove(); |
@@ -1800,6 +2043,7 @@ static int hv_pci_protocol_negotiation(struct hv_device *hdev) | |||
1800 | struct hv_pci_compl comp_pkt; | 2043 | struct hv_pci_compl comp_pkt; |
1801 | struct pci_packet *pkt; | 2044 | struct pci_packet *pkt; |
1802 | int ret; | 2045 | int ret; |
2046 | int i; | ||
1803 | 2047 | ||
1804 | /* | 2048 | /* |
1805 | * Initiate the handshake with the host and negotiate | 2049 | * Initiate the handshake with the host and negotiate |
@@ -1816,26 +2060,44 @@ static int hv_pci_protocol_negotiation(struct hv_device *hdev) | |||
1816 | pkt->compl_ctxt = &comp_pkt; | 2060 | pkt->compl_ctxt = &comp_pkt; |
1817 | version_req = (struct pci_version_request *)&pkt->message; | 2061 | version_req = (struct pci_version_request *)&pkt->message; |
1818 | version_req->message_type.type = PCI_QUERY_PROTOCOL_VERSION; | 2062 | version_req->message_type.type = PCI_QUERY_PROTOCOL_VERSION; |
1819 | version_req->protocol_version = PCI_PROTOCOL_VERSION_CURRENT; | ||
1820 | 2063 | ||
1821 | ret = vmbus_sendpacket(hdev->channel, version_req, | 2064 | for (i = 0; i < ARRAY_SIZE(pci_protocol_versions); i++) { |
1822 | sizeof(struct pci_version_request), | 2065 | version_req->protocol_version = pci_protocol_versions[i]; |
1823 | (unsigned long)pkt, VM_PKT_DATA_INBAND, | 2066 | ret = vmbus_sendpacket(hdev->channel, version_req, |
1824 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | 2067 | sizeof(struct pci_version_request), |
1825 | if (ret) | 2068 | (unsigned long)pkt, VM_PKT_DATA_INBAND, |
1826 | goto exit; | 2069 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); |
2070 | if (ret) { | ||
2071 | dev_err(&hdev->device, | ||
2072 | "PCI Pass-through VSP failed sending version reqquest: %#x", | ||
2073 | ret); | ||
2074 | goto exit; | ||
2075 | } | ||
1827 | 2076 | ||
1828 | wait_for_completion(&comp_pkt.host_event); | 2077 | wait_for_completion(&comp_pkt.host_event); |
1829 | 2078 | ||
1830 | if (comp_pkt.completion_status < 0) { | 2079 | if (comp_pkt.completion_status >= 0) { |
1831 | dev_err(&hdev->device, | 2080 | pci_protocol_version = pci_protocol_versions[i]; |
1832 | "PCI Pass-through VSP failed version request %x\n", | 2081 | dev_info(&hdev->device, |
1833 | comp_pkt.completion_status); | 2082 | "PCI VMBus probing: Using version %#x\n", |
1834 | ret = -EPROTO; | 2083 | pci_protocol_version); |
1835 | goto exit; | 2084 | goto exit; |
2085 | } | ||
2086 | |||
2087 | if (comp_pkt.completion_status != STATUS_REVISION_MISMATCH) { | ||
2088 | dev_err(&hdev->device, | ||
2089 | "PCI Pass-through VSP failed version request: %#x", | ||
2090 | comp_pkt.completion_status); | ||
2091 | ret = -EPROTO; | ||
2092 | goto exit; | ||
2093 | } | ||
2094 | |||
2095 | reinit_completion(&comp_pkt.host_event); | ||
1836 | } | 2096 | } |
1837 | 2097 | ||
1838 | ret = 0; | 2098 | dev_err(&hdev->device, |
2099 | "PCI pass-through VSP failed to find supported version"); | ||
2100 | ret = -EPROTO; | ||
1839 | 2101 | ||
1840 | exit: | 2102 | exit: |
1841 | kfree(pkt); | 2103 | kfree(pkt); |
@@ -2094,13 +2356,18 @@ static int hv_send_resources_allocated(struct hv_device *hdev) | |||
2094 | { | 2356 | { |
2095 | struct hv_pcibus_device *hbus = hv_get_drvdata(hdev); | 2357 | struct hv_pcibus_device *hbus = hv_get_drvdata(hdev); |
2096 | struct pci_resources_assigned *res_assigned; | 2358 | struct pci_resources_assigned *res_assigned; |
2359 | struct pci_resources_assigned2 *res_assigned2; | ||
2097 | struct hv_pci_compl comp_pkt; | 2360 | struct hv_pci_compl comp_pkt; |
2098 | struct hv_pci_dev *hpdev; | 2361 | struct hv_pci_dev *hpdev; |
2099 | struct pci_packet *pkt; | 2362 | struct pci_packet *pkt; |
2363 | size_t size_res; | ||
2100 | u32 wslot; | 2364 | u32 wslot; |
2101 | int ret; | 2365 | int ret; |
2102 | 2366 | ||
2103 | pkt = kmalloc(sizeof(*pkt) + sizeof(*res_assigned), GFP_KERNEL); | 2367 | size_res = (pci_protocol_version < PCI_PROTOCOL_VERSION_1_2) |
2368 | ? sizeof(*res_assigned) : sizeof(*res_assigned2); | ||
2369 | |||
2370 | pkt = kmalloc(sizeof(*pkt) + size_res, GFP_KERNEL); | ||
2104 | if (!pkt) | 2371 | if (!pkt) |
2105 | return -ENOMEM; | 2372 | return -ENOMEM; |
2106 | 2373 | ||
@@ -2111,22 +2378,30 @@ static int hv_send_resources_allocated(struct hv_device *hdev) | |||
2111 | if (!hpdev) | 2378 | if (!hpdev) |
2112 | continue; | 2379 | continue; |
2113 | 2380 | ||
2114 | memset(pkt, 0, sizeof(*pkt) + sizeof(*res_assigned)); | 2381 | memset(pkt, 0, sizeof(*pkt) + size_res); |
2115 | init_completion(&comp_pkt.host_event); | 2382 | init_completion(&comp_pkt.host_event); |
2116 | pkt->completion_func = hv_pci_generic_compl; | 2383 | pkt->completion_func = hv_pci_generic_compl; |
2117 | pkt->compl_ctxt = &comp_pkt; | 2384 | pkt->compl_ctxt = &comp_pkt; |
2118 | res_assigned = (struct pci_resources_assigned *)&pkt->message; | ||
2119 | res_assigned->message_type.type = PCI_RESOURCES_ASSIGNED; | ||
2120 | res_assigned->wslot.slot = hpdev->desc.win_slot.slot; | ||
2121 | 2385 | ||
2386 | if (pci_protocol_version < PCI_PROTOCOL_VERSION_1_2) { | ||
2387 | res_assigned = | ||
2388 | (struct pci_resources_assigned *)&pkt->message; | ||
2389 | res_assigned->message_type.type = | ||
2390 | PCI_RESOURCES_ASSIGNED; | ||
2391 | res_assigned->wslot.slot = hpdev->desc.win_slot.slot; | ||
2392 | } else { | ||
2393 | res_assigned2 = | ||
2394 | (struct pci_resources_assigned2 *)&pkt->message; | ||
2395 | res_assigned2->message_type.type = | ||
2396 | PCI_RESOURCES_ASSIGNED2; | ||
2397 | res_assigned2->wslot.slot = hpdev->desc.win_slot.slot; | ||
2398 | } | ||
2122 | put_pcichild(hpdev, hv_pcidev_ref_by_slot); | 2399 | put_pcichild(hpdev, hv_pcidev_ref_by_slot); |
2123 | 2400 | ||
2124 | ret = vmbus_sendpacket( | 2401 | ret = vmbus_sendpacket(hdev->channel, &pkt->message, |
2125 | hdev->channel, &pkt->message, | 2402 | size_res, (unsigned long)pkt, |
2126 | sizeof(*res_assigned), | 2403 | VM_PKT_DATA_INBAND, |
2127 | (unsigned long)pkt, | 2404 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); |
2128 | VM_PKT_DATA_INBAND, | ||
2129 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | ||
2130 | if (ret) | 2405 | if (ret) |
2131 | break; | 2406 | break; |
2132 | 2407 | ||
@@ -2204,11 +2479,19 @@ static int hv_pci_probe(struct hv_device *hdev, | |||
2204 | struct hv_pcibus_device *hbus; | 2479 | struct hv_pcibus_device *hbus; |
2205 | int ret; | 2480 | int ret; |
2206 | 2481 | ||
2207 | hbus = kzalloc(sizeof(*hbus), GFP_KERNEL); | 2482 | /* |
2483 | * hv_pcibus_device contains the hypercall arguments for retargeting in | ||
2484 | * hv_irq_unmask(). Those must not cross a page boundary. | ||
2485 | */ | ||
2486 | BUILD_BUG_ON(sizeof(*hbus) > PAGE_SIZE); | ||
2487 | |||
2488 | hbus = (struct hv_pcibus_device *)get_zeroed_page(GFP_KERNEL); | ||
2208 | if (!hbus) | 2489 | if (!hbus) |
2209 | return -ENOMEM; | 2490 | return -ENOMEM; |
2210 | hbus->state = hv_pcibus_init; | 2491 | hbus->state = hv_pcibus_init; |
2211 | 2492 | ||
2493 | hv_tmpcpumap_init(); | ||
2494 | |||
2212 | /* | 2495 | /* |
2213 | * The PCI bus "domain" is what is called "segment" in ACPI and | 2496 | * The PCI bus "domain" is what is called "segment" in ACPI and |
2214 | * other specs. Pull it from the instance ID, to get something | 2497 | * other specs. Pull it from the instance ID, to get something |
@@ -2308,7 +2591,7 @@ free_config: | |||
2308 | close: | 2591 | close: |
2309 | vmbus_close(hdev->channel); | 2592 | vmbus_close(hdev->channel); |
2310 | free_bus: | 2593 | free_bus: |
2311 | kfree(hbus); | 2594 | free_page((unsigned long)hbus); |
2312 | return ret; | 2595 | return ret; |
2313 | } | 2596 | } |
2314 | 2597 | ||
@@ -2386,7 +2669,7 @@ static int hv_pci_remove(struct hv_device *hdev) | |||
2386 | irq_domain_free_fwnode(hbus->sysdata.fwnode); | 2669 | irq_domain_free_fwnode(hbus->sysdata.fwnode); |
2387 | put_hvpcibus(hbus); | 2670 | put_hvpcibus(hbus); |
2388 | wait_for_completion(&hbus->remove_event); | 2671 | wait_for_completion(&hbus->remove_event); |
2389 | kfree(hbus); | 2672 | free_page((unsigned long)hbus); |
2390 | return 0; | 2673 | return 0; |
2391 | } | 2674 | } |
2392 | 2675 | ||