Browse code

Linux: Enable pci-hyperv support and apply relevant patches

Change-Id: I8a40ecdfd6b3d1d1d5243caf3e603e06c01d722f
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/6379
Reviewed-by: Srivatsa S. Bhat <srivatsab@vmware.com>
Tested-by: gerrit-photon <photon-checkins@vmware.com>

Ajay Kaher authored on 2018/12/18 03:27:59
Showing 5 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,97 @@
0
+From 0de8ce3ee8e38cc66683438f715c79a2cc69539e Mon Sep 17 00:00:00 2001
1
+From: Long Li <longli@microsoft.com>
2
+Date: Tue, 8 Nov 2016 14:04:38 -0800
3
+Subject: PCI: hv: Allocate physically contiguous hypercall params buffer
4
+
5
+hv_do_hypercall() assumes that we pass a segment from a physically
6
+contiguous buffer.  A buffer allocated on the stack may not work if
7
+CONFIG_VMAP_STACK=y is set.
8
+
9
+Use kmalloc() to allocate this buffer.
10
+
11
+Reported-by: Haiyang Zhang <haiyangz@microsoft.com>
12
+Signed-off-by: Long Li <longli@microsoft.com>
13
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
14
+Acked-by: K. Y. Srinivasan <kys@microsoft.com>
15
+Signed-off-by: Ajay Kaher <akaher@vmware.com>
16
+---
17
+ drivers/pci/host/pci-hyperv.c | 29 +++++++++++++++++++----------
18
+ 1 file changed, 19 insertions(+), 10 deletions(-)
19
+
20
+(limited to 'drivers/pci/host/pci-hyperv.c')
21
+
22
+diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c
23
+index a63c3a4f6c7c..3efcc7bdc5fb 100644
24
+--- a/drivers/pci/host/pci-hyperv.c
25
+@@ -378,6 +378,8 @@ struct hv_pcibus_device {
26
+ 	struct msi_domain_info msi_info;
27
+ 	struct msi_controller msi_chip;
28
+ 	struct irq_domain *irq_domain;
29
++	struct retarget_msi_interrupt retarget_msi_interrupt_params;
30
++	spinlock_t retarget_msi_interrupt_lock;
31
+ };
32
+ 
33
+ /*
34
+@@ -774,34 +776,40 @@ static void hv_irq_unmask(struct irq_data *data)
35
+ {
36
+ 	struct msi_desc *msi_desc = irq_data_get_msi_desc(data);
37
+ 	struct irq_cfg *cfg = irqd_cfg(data);
38
+-	struct retarget_msi_interrupt params;
39
++	struct retarget_msi_interrupt *params;
40
+ 	struct hv_pcibus_device *hbus;
41
+ 	struct cpumask *dest;
42
+ 	struct pci_bus *pbus;
43
+ 	struct pci_dev *pdev;
44
+ 	int cpu;
45
++	unsigned long flags;
46
+ 
47
+ 	dest = irq_data_get_affinity_mask(data);
48
+ 	pdev = msi_desc_to_pci_dev(msi_desc);
49
+ 	pbus = pdev->bus;
50
+ 	hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata);
51
+ 
52
+-	memset(&params, 0, sizeof(params));
53
+-	params.partition_id = HV_PARTITION_ID_SELF;
54
+-	params.source = 1; /* MSI(-X) */
55
+-	params.address = msi_desc->msg.address_lo;
56
+-	params.data = msi_desc->msg.data;
57
+-	params.device_id = (hbus->hdev->dev_instance.b[5] << 24) |
58
++	spin_lock_irqsave(&hbus->retarget_msi_interrupt_lock, flags);
59
++
60
++	params = &hbus->retarget_msi_interrupt_params;
61
++	memset(params, 0, sizeof(*params));
62
++	params->partition_id = HV_PARTITION_ID_SELF;
63
++	params->source = 1; /* MSI(-X) */
64
++	params->address = msi_desc->msg.address_lo;
65
++	params->data = msi_desc->msg.data;
66
++	params->device_id = (hbus->hdev->dev_instance.b[5] << 24) |
67
+ 			   (hbus->hdev->dev_instance.b[4] << 16) |
68
+ 			   (hbus->hdev->dev_instance.b[7] << 8) |
69
+ 			   (hbus->hdev->dev_instance.b[6] & 0xf8) |
70
+ 			   PCI_FUNC(pdev->devfn);
71
+-	params.vector = cfg->vector;
72
++	params->vector = cfg->vector;
73
+ 
74
+ 	for_each_cpu_and(cpu, dest, cpu_online_mask)
75
+-		params.vp_mask |= (1ULL << vmbus_cpu_number_to_vp_number(cpu));
76
++		params->vp_mask |= (1ULL << vmbus_cpu_number_to_vp_number(cpu));
77
++
78
++	hv_do_hypercall(HVCALL_RETARGET_INTERRUPT, params, NULL);
79
+ 
80
+-	hv_do_hypercall(HVCALL_RETARGET_INTERRUPT, &params, NULL);
81
++	spin_unlock_irqrestore(&hbus->retarget_msi_interrupt_lock, flags);
82
+ 
83
+ 	pci_msi_unmask_irq(data);
84
+ }
85
+@@ -2186,6 +2194,7 @@ static int hv_pci_probe(struct hv_device *hdev,
86
+ 	INIT_LIST_HEAD(&hbus->resources_for_children);
87
+ 	spin_lock_init(&hbus->config_lock);
88
+ 	spin_lock_init(&hbus->device_list_lock);
89
++	spin_lock_init(&hbus->retarget_msi_interrupt_lock);
90
+ 	sema_init(&hbus->enum_sem, 1);
91
+ 	init_completion(&hbus->remove_event);
92
+ 
93
+-- 
94
+cgit 1.2-0.3.lf.el7
95
+
0 96
new file mode 100644
... ...
@@ -0,0 +1,136 @@
0
+From b1db7e7e1d70035cbd0a7be32006af7714737157 Mon Sep 17 00:00:00 2001
1
+From: Jork Loeser <jloeser@microsoft.com>
2
+Date: Wed, 24 May 2017 13:41:27 -0700
3
+Subject: PCI: hv: Add vPCI version protocol negotiation
4
+
5
+Hyper-V vPCI offers different protocol versions.  Add the infra for
6
+negotiating the one to use.
7
+
8
+Signed-off-by: Jork Loeser <jloeser@microsoft.com>
9
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
10
+Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
11
+Acked-by: K. Y. Srinivasan <kys@microsoft.com>
12
+Signed-off-by: Ajay Kaher <akaher@vmware.com>
13
+---
14
+ drivers/pci/host/pci-hyperv.c | 72 +++++++++++++++++++++++++++++++------------
15
+ 1 file changed, 53 insertions(+), 19 deletions(-)
16
+
17
+(limited to 'drivers/pci/host/pci-hyperv.c')
18
+
19
+diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c
20
+index cf70fbc8e929..4a8a21e37b8e 100644
21
+--- a/drivers/pci/host/pci-hyperv.c
22
+@@ -64,22 +64,37 @@
23
+  * major version.
24
+  */
25
+ 
26
+-#define PCI_MAKE_VERSION(major, minor) ((u32)(((major) << 16) | (major)))
27
++#define PCI_MAKE_VERSION(major, minor) ((u32)(((major) << 16) | (minor)))
28
+ #define PCI_MAJOR_VERSION(version) ((u32)(version) >> 16)
29
+ #define PCI_MINOR_VERSION(version) ((u32)(version) & 0xff)
30
+ 
31
+-enum {
32
+-	PCI_PROTOCOL_VERSION_1_1 = PCI_MAKE_VERSION(1, 1),
33
+-	PCI_PROTOCOL_VERSION_CURRENT = PCI_PROTOCOL_VERSION_1_1
34
++enum pci_protocol_version_t {
35
++	PCI_PROTOCOL_VERSION_1_1 = PCI_MAKE_VERSION(1, 1),	/* Win10 */
36
+ };
37
+ 
38
+ #define CPU_AFFINITY_ALL	-1ULL
39
++
40
++/*
41
++ * Supported protocol versions in the order of probing - highest go
42
++ * first.
43
++ */
44
++static enum pci_protocol_version_t pci_protocol_versions[] = {
45
++	PCI_PROTOCOL_VERSION_1_1,
46
++};
47
++
48
++/*
49
++ * Protocol version negotiated by hv_pci_protocol_negotiation().
50
++ */
51
++static enum pci_protocol_version_t pci_protocol_version;
52
++
53
+ #define PCI_CONFIG_MMIO_LENGTH	0x2000
54
+ #define CFG_PAGE_OFFSET 0x1000
55
+ #define CFG_PAGE_SIZE (PCI_CONFIG_MMIO_LENGTH - CFG_PAGE_OFFSET)
56
+ 
57
+ #define MAX_SUPPORTED_MSI_MESSAGES 0x400
58
+ 
59
++#define STATUS_REVISION_MISMATCH 0xC0000059
60
++
61
+ /*
62
+  * Message Types
63
+  */
64
+@@ -1849,6 +1864,7 @@ static int hv_pci_protocol_negotiation(struct hv_device *hdev)
65
+ 	struct hv_pci_compl comp_pkt;
66
+ 	struct pci_packet *pkt;
67
+ 	int ret;
68
++	int i;
69
+ 
70
+ 	/*
71
+ 	 * Initiate the handshake with the host and negotiate
72
+@@ -1865,26 +1881,44 @@ static int hv_pci_protocol_negotiation(struct hv_device *hdev)
73
+ 	pkt->compl_ctxt = &comp_pkt;
74
+ 	version_req = (struct pci_version_request *)&pkt->message;
75
+ 	version_req->message_type.type = PCI_QUERY_PROTOCOL_VERSION;
76
+-	version_req->protocol_version = PCI_PROTOCOL_VERSION_CURRENT;
77
+ 
78
+-	ret = vmbus_sendpacket(hdev->channel, version_req,
79
+-			       sizeof(struct pci_version_request),
80
+-			       (unsigned long)pkt, VM_PKT_DATA_INBAND,
81
+-			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
82
+-	if (ret)
83
+-		goto exit;
84
++	for (i = 0; i < ARRAY_SIZE(pci_protocol_versions); i++) {
85
++		version_req->protocol_version = pci_protocol_versions[i];
86
++		ret = vmbus_sendpacket(hdev->channel, version_req,
87
++				sizeof(struct pci_version_request),
88
++				(unsigned long)pkt, VM_PKT_DATA_INBAND,
89
++				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
90
++		if (ret) {
91
++			dev_err(&hdev->device,
92
++				"PCI Pass-through VSP failed sending version reqquest: %#x",
93
++				ret);
94
++			goto exit;
95
++		}
96
+ 
97
+-	wait_for_completion(&comp_pkt.host_event);
98
++		wait_for_completion(&comp_pkt.host_event);
99
+ 
100
+-	if (comp_pkt.completion_status < 0) {
101
+-		dev_err(&hdev->device,
102
+-			"PCI Pass-through VSP failed version request %x\n",
103
+-			comp_pkt.completion_status);
104
+-		ret = -EPROTO;
105
+-		goto exit;
106
++		if (comp_pkt.completion_status >= 0) {
107
++			pci_protocol_version = pci_protocol_versions[i];
108
++			dev_info(&hdev->device,
109
++				"PCI VMBus probing: Using version %#x\n",
110
++				pci_protocol_version);
111
++			goto exit;
112
++		}
113
++
114
++		if (comp_pkt.completion_status != STATUS_REVISION_MISMATCH) {
115
++			dev_err(&hdev->device,
116
++				"PCI Pass-through VSP failed version request: %#x",
117
++				comp_pkt.completion_status);
118
++			ret = -EPROTO;
119
++			goto exit;
120
++		}
121
++
122
++		reinit_completion(&comp_pkt.host_event);
123
+ 	}
124
+ 
125
+-	ret = 0;
126
++	dev_err(&hdev->device,
127
++		"PCI pass-through VSP failed to find supported version");
128
++	ret = -EPROTO;
129
+ 
130
+ exit:
131
+ 	kfree(pkt);
132
+-- 
133
+cgit 1.2-0.3.lf.el7
134
+
0 135
new file mode 100755
... ...
@@ -0,0 +1,465 @@
0
+From 7dcf90e9e032432e91ce77dd872d2227e9d5b741 Mon Sep 17 00:00:00 2001
1
+From: Jork Loeser <jloeser@microsoft.com>
2
+Date: Wed, 24 May 2017 13:41:28 -0700
3
+Subject: PCI: hv: Use vPCI protocol version 1.2
4
+
5
+Update the Hyper-V vPCI driver to use the Server-2016 version of the vPCI
6
+protocol, fixing MSI creation and retargeting issues.
7
+
8
+Replaced hv_tmp_cpu_nr_to_vp_nr() with vmbus_cpu_number_to_vp_number()
9
+to make this patch compatibale for linux v4.9.
10
+
11
+Signed-off-by: Jork Loeser <jloeser@microsoft.com>
12
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
13
+Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
14
+Acked-by: K. Y. Srinivasan <kys@microsoft.com>
15
+Signed-off-by: Ajay Kaher <akaher@vmware.com>
16
+---
17
+ drivers/pci/host/pci-hyperv.c | 300 ++++++++++++++++++++++++++++++++++--------
18
+ 1 file changed, 246 insertions(+), 54 deletions(-)
19
+
20
+(limited to 'drivers/pci/host/pci-hyperv.c')
21
+
22
+diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c
23
+index 4a8a21e37b8e..415dcc69a502 100644
24
+--- a/drivers/pci/host/pci-hyperv.c
25
+@@ -70,6 +70,7 @@
26
+ 
27
+ enum pci_protocol_version_t {
28
+ 	PCI_PROTOCOL_VERSION_1_1 = PCI_MAKE_VERSION(1, 1),	/* Win10 */
29
++	PCI_PROTOCOL_VERSION_1_2 = PCI_MAKE_VERSION(1, 2),	/* RS1 */
30
+ };
31
+ 
32
+ #define CPU_AFFINITY_ALL	-1ULL
33
+@@ -79,6 +80,7 @@ enum pci_protocol_version_t {
34
+  * first.
35
+  */
36
+ static enum pci_protocol_version_t pci_protocol_versions[] = {
37
++	PCI_PROTOCOL_VERSION_1_2,
38
+ 	PCI_PROTOCOL_VERSION_1_1,
39
+ };
40
+ 
41
+@@ -124,6 +126,9 @@ enum pci_message_type {
42
+ 	PCI_QUERY_PROTOCOL_VERSION      = PCI_MESSAGE_BASE + 0x13,
43
+ 	PCI_CREATE_INTERRUPT_MESSAGE    = PCI_MESSAGE_BASE + 0x14,
44
+ 	PCI_DELETE_INTERRUPT_MESSAGE    = PCI_MESSAGE_BASE + 0x15,
45
++	PCI_RESOURCES_ASSIGNED2		= PCI_MESSAGE_BASE + 0x16,
46
++	PCI_CREATE_INTERRUPT_MESSAGE2	= PCI_MESSAGE_BASE + 0x17,
47
++	PCI_DELETE_INTERRUPT_MESSAGE2	= PCI_MESSAGE_BASE + 0x18, /* unused */
48
+ 	PCI_MESSAGE_MAXIMUM
49
+ };
50
+ 
51
+@@ -193,6 +198,30 @@ struct hv_msi_desc {
52
+ 	u64	cpu_mask;
53
+ } __packed;
54
+ 
55
++/**
56
++ * struct hv_msi_desc2 - 1.2 version of hv_msi_desc
57
++ * @vector:		IDT entry
58
++ * @delivery_mode:	As defined in Intel's Programmer's
59
++ *			Reference Manual, Volume 3, Chapter 8.
60
++ * @vector_count:	Number of contiguous entries in the
61
++ *			Interrupt Descriptor Table that are
62
++ *			occupied by this Message-Signaled
63
++ *			Interrupt. For "MSI", as first defined
64
++ *			in PCI 2.2, this can be between 1 and
65
++ *			32. For "MSI-X," as first defined in PCI
66
++ *			3.0, this must be 1, as each MSI-X table
67
++ *			entry would have its own descriptor.
68
++ * @processor_count:	number of bits enabled in array.
69
++ * @processor_array:	All the target virtual processors.
70
++ */
71
++struct hv_msi_desc2 {
72
++	u8	vector;
73
++	u8	delivery_mode;
74
++	u16	vector_count;
75
++	u16	processor_count;
76
++	u16	processor_array[32];
77
++} __packed;
78
++
79
+ /**
80
+  * struct tran_int_desc
81
+  * @reserved:		unused, padding
82
+@@ -309,6 +338,14 @@ struct pci_resources_assigned {
83
+ 	u32 reserved[4];
84
+ } __packed;
85
+ 
86
++struct pci_resources_assigned2 {
87
++	struct pci_message message_type;
88
++	union win_slot_encoding wslot;
89
++	u8 memory_range[0x14][6];	/* not used here */
90
++	u32 msi_descriptor_count;
91
++	u8 reserved[70];
92
++} __packed;
93
++
94
+ struct pci_create_interrupt {
95
+ 	struct pci_message message_type;
96
+ 	union win_slot_encoding wslot;
97
+@@ -321,6 +358,12 @@ struct pci_create_int_response {
98
+ 	struct tran_int_desc int_desc;
99
+ } __packed;
100
+ 
101
++struct pci_create_interrupt2 {
102
++	struct pci_message message_type;
103
++	union win_slot_encoding wslot;
104
++	struct hv_msi_desc2 int_desc;
105
++} __packed;
106
++
107
+ struct pci_delete_interrupt {
108
+ 	struct pci_message message_type;
109
+ 	union win_slot_encoding wslot;
110
+@@ -346,17 +389,42 @@ static int pci_ring_size = (4 * PAGE_SIZE);
111
+ #define HV_PARTITION_ID_SELF		((u64)-1)
112
+ #define HVCALL_RETARGET_INTERRUPT	0x7e
113
+ 
114
+-struct retarget_msi_interrupt {
115
+-	u64	partition_id;		/* use "self" */
116
+-	u64	device_id;
117
++struct hv_interrupt_entry {
118
+ 	u32	source;			/* 1 for MSI(-X) */
119
+ 	u32	reserved1;
120
+ 	u32	address;
121
+ 	u32	data;
122
+-	u64	reserved2;
123
++};
124
++
125
++#define HV_VP_SET_BANK_COUNT_MAX	5 /* current implementation limit */
126
++
127
++struct hv_vp_set {
128
++	u64	format;			/* 0 (HvGenericSetSparse4k) */
129
++	u64	valid_banks;
130
++	u64	masks[HV_VP_SET_BANK_COUNT_MAX];
131
++};
132
++
133
++/*
134
++ * flags for hv_device_interrupt_target.flags
135
++ */
136
++#define HV_DEVICE_INTERRUPT_TARGET_MULTICAST		1
137
++#define HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET	2
138
++
139
++struct hv_device_interrupt_target {
140
+ 	u32	vector;
141
+ 	u32	flags;
142
+-	u64	vp_mask;
143
++	union {
144
++		u64		 vp_mask;
145
++		struct hv_vp_set vp_set;
146
++	};
147
++};
148
++
149
++struct retarget_msi_interrupt {
150
++	u64	partition_id;		/* use "self" */
151
++	u64	device_id;
152
++	struct hv_interrupt_entry int_entry;
153
++	u64	reserved2;
154
++	struct hv_device_interrupt_target int_target;
155
+ } __packed;
156
+ 
157
+ /*
158
+@@ -850,8 +918,11 @@ static void hv_irq_unmask(struct irq_data *data)
159
+ 	struct cpumask *dest;
160
+ 	struct pci_bus *pbus;
161
+ 	struct pci_dev *pdev;
162
+-	int cpu;
163
+ 	unsigned long flags;
164
++	u32 var_size = 0;
165
++	int cpu_vmbus;
166
++	int cpu;
167
++	u64 res;
168
+ 
169
+ 	dest = irq_data_get_affinity_mask(data);
170
+ 	pdev = msi_desc_to_pci_dev(msi_desc);
171
+@@ -863,23 +934,74 @@ static void hv_irq_unmask(struct irq_data *data)
172
+ 	params = &hbus->retarget_msi_interrupt_params;
173
+ 	memset(params, 0, sizeof(*params));
174
+ 	params->partition_id = HV_PARTITION_ID_SELF;
175
+-	params->source = 1; /* MSI(-X) */
176
+-	params->address = msi_desc->msg.address_lo;
177
+-	params->data = msi_desc->msg.data;
178
++	params->int_entry.source = 1; /* MSI(-X) */
179
++	params->int_entry.address = msi_desc->msg.address_lo;
180
++	params->int_entry.data = msi_desc->msg.data;
181
+ 	params->device_id = (hbus->hdev->dev_instance.b[5] << 24) |
182
+ 			   (hbus->hdev->dev_instance.b[4] << 16) |
183
+ 			   (hbus->hdev->dev_instance.b[7] << 8) |
184
+ 			   (hbus->hdev->dev_instance.b[6] & 0xf8) |
185
+ 			   PCI_FUNC(pdev->devfn);
186
+-	params->vector = cfg->vector;
187
++	params->int_target.vector = cfg->vector;
188
++
189
++	/*
190
++	 * Honoring apic->irq_delivery_mode set to dest_Fixed by
191
++	 * setting the HV_DEVICE_INTERRUPT_TARGET_MULTICAST flag results in a
192
++	 * spurious interrupt storm. Not doing so does not seem to have a
193
++	 * negative effect (yet?).
194
++	 */
195
++
196
++	if (pci_protocol_version >= PCI_PROTOCOL_VERSION_1_2) {
197
++		/*
198
++		 * PCI_PROTOCOL_VERSION_1_2 supports the VP_SET version of the
199
++		 * HVCALL_RETARGET_INTERRUPT hypercall, which also coincides
200
++		 * with >64 VP support.
201
++		 * ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED
202
++		 * is not sufficient for this hypercall.
203
++		 */
204
++		params->int_target.flags |=
205
++			HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET;
206
++		params->int_target.vp_set.valid_banks =
207
++			(1ull << HV_VP_SET_BANK_COUNT_MAX) - 1;
208
++
209
++		/*
210
++		 * var-sized hypercall, var-size starts after vp_mask (thus
211
++		 * vp_set.format does not count, but vp_set.valid_banks does).
212
++		 */
213
++		var_size = 1 + HV_VP_SET_BANK_COUNT_MAX;
214
++
215
++		for_each_cpu_and(cpu, dest, cpu_online_mask) {
216
++			cpu_vmbus = vmbus_cpu_number_to_vp_number(cpu);
217
++
218
++			if (cpu_vmbus >= HV_VP_SET_BANK_COUNT_MAX * 64) {
219
++				dev_err(&hbus->hdev->device,
220
++					"too high CPU %d", cpu_vmbus);
221
++				res = 1;
222
++				goto exit_unlock;
223
++			}
224
+ 
225
+-	for_each_cpu_and(cpu, dest, cpu_online_mask)
226
+-		params->vp_mask |= (1ULL << vmbus_cpu_number_to_vp_number(cpu));
227
++			params->int_target.vp_set.masks[cpu_vmbus / 64] |=
228
++				(1ULL << (cpu_vmbus & 63));
229
++		}
230
++	} else {
231
++		for_each_cpu_and(cpu, dest, cpu_online_mask) {
232
++			params->int_target.vp_mask |=
233
++				(1ULL << vmbus_cpu_number_to_vp_number(cpu));
234
++		}
235
++	}
236
+ 
237
+-	hv_do_hypercall(HVCALL_RETARGET_INTERRUPT, params, NULL);
238
++	res = hv_do_hypercall(HVCALL_RETARGET_INTERRUPT | (var_size << 17),
239
++			      params, NULL);
240
+ 
241
++exit_unlock:
242
+ 	spin_unlock_irqrestore(&hbus->retarget_msi_interrupt_lock, flags);
243
+ 
244
++	if (res) {
245
++		dev_err(&hbus->hdev->device,
246
++			"%s() failed: %#llx", __func__, res);
247
++		return;
248
++	}
249
++
250
+ 	pci_msi_unmask_irq(data);
251
+ }
252
+ 
253
+@@ -900,6 +1022,53 @@ static void hv_pci_compose_compl(void *context, struct pci_response *resp,
254
+ 	complete(&comp_pkt->comp_pkt.host_event);
255
+ }
256
+ 
257
++static u32 hv_compose_msi_req_v1(
258
++	struct pci_create_interrupt *int_pkt, struct cpumask *affinity,
259
++	u32 slot, u8 vector)
260
++{
261
++	int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE;
262
++	int_pkt->wslot.slot = slot;
263
++	int_pkt->int_desc.vector = vector;
264
++	int_pkt->int_desc.vector_count = 1;
265
++	int_pkt->int_desc.delivery_mode =
266
++		(apic->irq_delivery_mode == dest_LowestPrio) ?
267
++			dest_LowestPrio : dest_Fixed;
268
++
269
++	/*
270
++	 * Create MSI w/ dummy vCPU set, overwritten by subsequent retarget in
271
++	 * hv_irq_unmask().
272
++	 */
273
++	int_pkt->int_desc.cpu_mask = CPU_AFFINITY_ALL;
274
++
275
++	return sizeof(*int_pkt);
276
++}
277
++
278
++static u32 hv_compose_msi_req_v2(
279
++	struct pci_create_interrupt2 *int_pkt, struct cpumask *affinity,
280
++	u32 slot, u8 vector)
281
++{
282
++	int cpu;
283
++
284
++	int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE2;
285
++	int_pkt->wslot.slot = slot;
286
++	int_pkt->int_desc.vector = vector;
287
++	int_pkt->int_desc.vector_count = 1;
288
++	int_pkt->int_desc.delivery_mode =
289
++		(apic->irq_delivery_mode == dest_LowestPrio) ?
290
++			dest_LowestPrio : dest_Fixed;
291
++
292
++	/*
293
++	 * Create MSI w/ dummy vCPU set targeting just one vCPU, overwritten
294
++	 * by subsequent retarget in hv_irq_unmask().
295
++	 */
296
++	cpu = cpumask_first_and(affinity, cpu_online_mask);
297
++	int_pkt->int_desc.processor_array[0] =
298
++		vmbus_cpu_number_to_vp_number(cpu);
299
++	int_pkt->int_desc.processor_count = 1;
300
++
301
++	return sizeof(*int_pkt);
302
++}
303
++
304
+ /**
305
+  * hv_compose_msi_msg() - Supplies a valid MSI address/data
306
+  * @data:	Everything about this MSI
307
+@@ -918,15 +1087,17 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
308
+ 	struct hv_pci_dev *hpdev;
309
+ 	struct pci_bus *pbus;
310
+ 	struct pci_dev *pdev;
311
+-	struct pci_create_interrupt *int_pkt;
312
+ 	struct compose_comp_ctxt comp;
313
+ 	struct tran_int_desc *int_desc;
314
+-	struct cpumask *affinity;
315
+ 	struct {
316
+-		struct pci_packet pkt;
317
+-		u8 buffer[sizeof(struct pci_create_interrupt)];
318
+-	} ctxt;
319
+-	int cpu;
320
++		struct pci_packet pci_pkt;
321
++		union {
322
++			struct pci_create_interrupt v1;
323
++			struct pci_create_interrupt2 v2;
324
++		} int_pkts;
325
++	} __packed ctxt;
326
++
327
++	u32 size;
328
+ 	int ret;
329
+ 
330
+ 	pdev = msi_desc_to_pci_dev(irq_data_get_msi_desc(data));
331
+@@ -949,36 +1120,44 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
332
+ 
333
+ 	memset(&ctxt, 0, sizeof(ctxt));
334
+ 	init_completion(&comp.comp_pkt.host_event);
335
+-	ctxt.pkt.completion_func = hv_pci_compose_compl;
336
+-	ctxt.pkt.compl_ctxt = &comp;
337
+-	int_pkt = (struct pci_create_interrupt *)&ctxt.pkt.message;
338
+-	int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE;
339
+-	int_pkt->wslot.slot = hpdev->desc.win_slot.slot;
340
+-	int_pkt->int_desc.vector = cfg->vector;
341
+-	int_pkt->int_desc.vector_count = 1;
342
+-	int_pkt->int_desc.delivery_mode =
343
+-		(apic->irq_delivery_mode == dest_LowestPrio) ? 1 : 0;
344
++	ctxt.pci_pkt.completion_func = hv_pci_compose_compl;
345
++	ctxt.pci_pkt.compl_ctxt = &comp;
346
++
347
++	switch (pci_protocol_version) {
348
++	case PCI_PROTOCOL_VERSION_1_1:
349
++		size = hv_compose_msi_req_v1(&ctxt.int_pkts.v1,
350
++					irq_data_get_affinity_mask(data),
351
++					hpdev->desc.win_slot.slot,
352
++					cfg->vector);
353
++		break;
354
+ 
355
+-	/*
356
+-	 * This bit doesn't have to work on machines with more than 64
357
+-	 * processors because Hyper-V only supports 64 in a guest.
358
+-	 */
359
+-	affinity = irq_data_get_affinity_mask(data);
360
+-	if (cpumask_weight(affinity) >= 32) {
361
+-		int_pkt->int_desc.cpu_mask = CPU_AFFINITY_ALL;
362
+-	} else {
363
+-		for_each_cpu_and(cpu, affinity, cpu_online_mask) {
364
+-			int_pkt->int_desc.cpu_mask |=
365
+-				(1ULL << vmbus_cpu_number_to_vp_number(cpu));
366
+-		}
367
++	case PCI_PROTOCOL_VERSION_1_2:
368
++		size = hv_compose_msi_req_v2(&ctxt.int_pkts.v2,
369
++					irq_data_get_affinity_mask(data),
370
++					hpdev->desc.win_slot.slot,
371
++					cfg->vector);
372
++		break;
373
++
374
++	default:
375
++		/* As we only negotiate protocol versions known to this driver,
376
++		 * this path should never hit. However, this is it not a hot
377
++		 * path so we print a message to aid future updates.
378
++		 */
379
++		dev_err(&hbus->hdev->device,
380
++			"Unexpected vPCI protocol, update driver.");
381
++		goto free_int_desc;
382
+ 	}
383
+ 
384
+-	ret = vmbus_sendpacket(hpdev->hbus->hdev->channel, int_pkt,
385
+-			       sizeof(*int_pkt), (unsigned long)&ctxt.pkt,
386
++	ret = vmbus_sendpacket(hpdev->hbus->hdev->channel, &ctxt.int_pkts,
387
++			       size, (unsigned long)&ctxt.pci_pkt,
388
+ 			       VM_PKT_DATA_INBAND,
389
+ 			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
390
+-	if (ret)
391
++	if (ret) {
392
++		dev_err(&hbus->hdev->device,
393
++			"Sending request for interrupt failed: 0x%x",
394
++			comp.comp_pkt.completion_status);
395
+ 		goto free_int_desc;
396
++	}
397
+ 
398
+ 	wait_for_completion(&comp.comp_pkt.host_event);
399
+ 
400
+@@ -2177,13 +2356,18 @@ static int hv_send_resources_allocated(struct hv_device *hdev)
401
+ {
402
+ 	struct hv_pcibus_device *hbus = hv_get_drvdata(hdev);
403
+ 	struct pci_resources_assigned *res_assigned;
404
++	struct pci_resources_assigned2 *res_assigned2;
405
+ 	struct hv_pci_compl comp_pkt;
406
+ 	struct hv_pci_dev *hpdev;
407
+ 	struct pci_packet *pkt;
408
++	size_t size_res;
409
+ 	u32 wslot;
410
+ 	int ret;
411
+ 
412
+-	pkt = kmalloc(sizeof(*pkt) + sizeof(*res_assigned), GFP_KERNEL);
413
++	size_res = (pci_protocol_version < PCI_PROTOCOL_VERSION_1_2)
414
++			? sizeof(*res_assigned) : sizeof(*res_assigned2);
415
++
416
++	pkt = kmalloc(sizeof(*pkt) + size_res, GFP_KERNEL);
417
+ 	if (!pkt)
418
+ 		return -ENOMEM;
419
+ 
420
+@@ -2194,22 +2378,30 @@ static int hv_send_resources_allocated(struct hv_device *hdev)
421
+ 		if (!hpdev)
422
+ 			continue;
423
+ 
424
+-		memset(pkt, 0, sizeof(*pkt) + sizeof(*res_assigned));
425
++		memset(pkt, 0, sizeof(*pkt) + size_res);
426
+ 		init_completion(&comp_pkt.host_event);
427
+ 		pkt->completion_func = hv_pci_generic_compl;
428
+ 		pkt->compl_ctxt = &comp_pkt;
429
+-		res_assigned = (struct pci_resources_assigned *)&pkt->message;
430
+-		res_assigned->message_type.type = PCI_RESOURCES_ASSIGNED;
431
+-		res_assigned->wslot.slot = hpdev->desc.win_slot.slot;
432
+ 
433
++		if (pci_protocol_version < PCI_PROTOCOL_VERSION_1_2) {
434
++			res_assigned =
435
++				(struct pci_resources_assigned *)&pkt->message;
436
++			res_assigned->message_type.type =
437
++				PCI_RESOURCES_ASSIGNED;
438
++			res_assigned->wslot.slot = hpdev->desc.win_slot.slot;
439
++		} else {
440
++			res_assigned2 =
441
++				(struct pci_resources_assigned2 *)&pkt->message;
442
++			res_assigned2->message_type.type =
443
++				PCI_RESOURCES_ASSIGNED2;
444
++			res_assigned2->wslot.slot = hpdev->desc.win_slot.slot;
445
++		}
446
+ 		put_pcichild(hpdev, hv_pcidev_ref_by_slot);
447
+ 
448
+-		ret = vmbus_sendpacket(
449
+-			hdev->channel, &pkt->message,
450
+-			sizeof(*res_assigned),
451
+-			(unsigned long)pkt,
452
+-			VM_PKT_DATA_INBAND,
453
+-			VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
454
++		ret = vmbus_sendpacket(hdev->channel, &pkt->message,
455
++				size_res, (unsigned long)pkt,
456
++				VM_PKT_DATA_INBAND,
457
++				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
458
+ 		if (ret)
459
+ 			break;
460
+ 
461
+-- 
462
+cgit 1.2-0.3.lf.el7
463
+
0 464
old mode 100644
1 465
new mode 100755
... ...
@@ -1,6 +1,6 @@
1 1
 #
2 2
 # Automatically generated file; DO NOT EDIT.
3
-# Linux/x86 4.9.120 Kernel Configuration
3
+# Linux/x86 4.9.140 Kernel Configuration
4 4
 #
5 5
 CONFIG_64BIT=y
6 6
 CONFIG_X86_64=y
... ...
@@ -770,7 +770,7 @@ CONFIG_PCI_IOV=y
770 770
 CONFIG_PCI_PRI=y
771 771
 CONFIG_PCI_PASID=y
772 772
 CONFIG_PCI_LABEL=y
773
-# CONFIG_PCI_HYPERV is not set
773
+CONFIG_PCI_HYPERV=m
774 774
 CONFIG_HOTPLUG_PCI=y
775 775
 CONFIG_HOTPLUG_PCI_ACPI=y
776 776
 CONFIG_HOTPLUG_PCI_ACPI_IBM=m
... ...
@@ -1384,6 +1384,7 @@ CONFIG_VSOCKETS=m
1384 1384
 CONFIG_VMWARE_VMCI_VSOCKETS=m
1385 1385
 CONFIG_VIRTIO_VSOCKETS=m
1386 1386
 CONFIG_VIRTIO_VSOCKETS_COMMON=m
1387
+CONFIG_HYPERV_SOCK=m
1387 1388
 CONFIG_NETLINK_DIAG=m
1388 1389
 CONFIG_MPLS=y
1389 1390
 CONFIG_NET_MPLS_GSO=m
... ...
@@ -2,7 +2,7 @@
2 2
 Summary:        Kernel
3 3
 Name:           linux
4 4
 Version:        4.9.140
5
-Release:        1%{?kat_build:.%kat_build}%{?dist}
5
+Release:        2%{?kat_build:.%kat_build}%{?dist}
6 6
 License:    	GPLv2
7 7
 URL:        	http://www.kernel.org/
8 8
 Group:        	System Environment/Kernel
... ...
@@ -71,6 +71,11 @@ Patch46:        0001-xfs-move-inode-fork-verifiers-to-xfs-dinode-verify.patch
71 71
 Patch47:        0002-xfs-verify-dinode-header-first.patch
72 72
 Patch48:        0003-xfs-enhance-dinode-verifier.patch
73 73
 
74
+#HyperV PCI patches
75
+Patch51:        0001_PCI_hv_Allocate_physically_contiguous_hypercall_params_buffer.patch
76
+Patch52:        0002_PCI_hv_Add_vPCI_version_protocol_negotiation.patch
77
+Patch53:        0003_PCI_hv_Use_vPCI_protocol_version_1.2_v4.9.patch
78
+
74 79
 # Out-of-tree patches from AppArmor:
75 80
 Patch71: 0001-UBUNTU-SAUCE-AppArmor-basic-networking-rules.patch
76 81
 Patch72: 0002-apparmor-Fix-quieting-of-audit-messages-for-network-.patch
... ...
@@ -190,6 +195,10 @@ This package contains the 'perf' performance analysis tools for Linux kernel.
190 190
 %patch47 -p1
191 191
 %patch48 -p1
192 192
 
193
+%patch51 -p1
194
+%patch52 -p1
195
+%patch53 -p1
196
+
193 197
 %patch71 -p1
194 198
 %patch72 -p1
195 199
 %patch73 -p1
... ...
@@ -363,6 +372,8 @@ ln -sf %{name}-%{uname_r}.cfg /boot/photon.cfg
363 363
 /usr/share/doc/*
364 364
 
365 365
 %changelog
366
+*   Mon Dec 17 2018 Ajay Kaher <akaher@vmware.com> 4.9.140-2
367
+-   Enable pci-hyperv support and apply relevant patches
366 368
 *   Mon Nov 26 2018 Srivatsa S. Bhat (VMware) <srivatsa@csail.mit.edu> 4.9.140-1
367 369
 -   Update to version 4.9.140
368 370
 *   Fri Nov 16 2018 Srivatsa S. Bhat (VMware) <srivatsa@csail.mit.edu> 4.9.137-1