Blame view
drivers/hv/channel_mgmt.c
17.4 KB
3e7ee4902 Staging: hv: add ... |
1 |
/* |
3e7ee4902 Staging: hv: add ... |
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
* Copyright (c) 2009, Microsoft Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307 USA. * * Authors: * Haiyang Zhang <haiyangz@microsoft.com> * Hank Janssen <hjanssen@microsoft.com> |
3e7ee4902 Staging: hv: add ... |
20 |
*/ |
0a46618d5 staging: hv: Repl... |
21 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
a0086dc51 Staging: hv: remo... |
22 |
#include <linux/kernel.h> |
0c3b7b2f7 Staging: hv: Use ... |
23 24 |
#include <linux/sched.h> #include <linux/wait.h> |
a0086dc51 Staging: hv: remo... |
25 |
#include <linux/mm.h> |
5a0e3ad6a include cleanup: ... |
26 |
#include <linux/slab.h> |
53af545b2 Staging: hv: remo... |
27 |
#include <linux/list.h> |
c88c4e4c7 Staging: hv: Adde... |
28 |
#include <linux/module.h> |
8b5d6d3bd staging: hv: Fix ... |
29 |
#include <linux/completion.h> |
46a971913 Staging: hv: move... |
30 |
#include <linux/hyperv.h> |
3f335ea21 Staging: hv: Incl... |
31 |
|
0f2a6619e Staging: hv: vmbu... |
32 |
#include "hyperv_vmbus.h" |
3e7ee4902 Staging: hv: add ... |
33 |
|
1d7e907fb Staging: hv: remo... |
34 |
struct vmbus_channel_message_table_entry { |
cf9dcba7f Staging: hv: vmbu... |
35 |
enum vmbus_channel_message_type message_type; |
fa90f1de2 Staging: hv: vmbu... |
36 |
void (*message_handler)(struct vmbus_channel_message_header *msg); |
1d7e907fb Staging: hv: remo... |
37 |
}; |
3e7ee4902 Staging: hv: add ... |
38 |
|
245ba56a5 Staging: hv: Impl... |
39 40 |
#define MAX_MSG_TYPES 4 #define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8 |
c88c4e4c7 Staging: hv: Adde... |
41 |
|
358d2ee2e Staging: hv: Repl... |
42 |
static const uuid_le |
50b03266b Staging: hv: vmbu... |
43 |
supported_device_classes[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = { |
454f18a96 Staging: hv: Remo... |
44 |
/* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */ |
caf26a31b Staging: hv: osd.... |
45 46 |
/* Storage - SCSI */ { |
358d2ee2e Staging: hv: Repl... |
47 |
.b = { |
caf26a31b Staging: hv: osd.... |
48 49 50 51 |
0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f } }, |
454f18a96 Staging: hv: Remo... |
52 |
/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */ |
caf26a31b Staging: hv: osd.... |
53 54 |
/* Network */ { |
358d2ee2e Staging: hv: Repl... |
55 |
.b = { |
caf26a31b Staging: hv: osd.... |
56 57 58 59 |
0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E } }, |
454f18a96 Staging: hv: Remo... |
60 |
/* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */ |
caf26a31b Staging: hv: osd.... |
61 62 |
/* Input */ { |
358d2ee2e Staging: hv: Repl... |
63 |
.b = { |
caf26a31b Staging: hv: osd.... |
64 65 66 67 |
0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A } }, |
3e7ee4902 Staging: hv: add ... |
68 |
|
caf26a31b Staging: hv: osd.... |
69 70 71 |
/* {32412632-86cb-44a2-9b5c-50d1417354f5} */ /* IDE */ { |
358d2ee2e Staging: hv: Repl... |
72 |
.b = { |
caf26a31b Staging: hv: osd.... |
73 74 75 76 |
0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 } }, |
c88c4e4c7 Staging: hv: Adde... |
77 78 79 |
/* 0E0B6031-5213-4934-818B-38D90CED39DB */ /* Shutdown */ { |
358d2ee2e Staging: hv: Repl... |
80 |
.b = { |
c88c4e4c7 Staging: hv: Adde... |
81 82 83 84 |
0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB } }, |
39c4e9c37 Staging: hv: Add ... |
85 86 87 |
/* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */ /* TimeSync */ { |
358d2ee2e Staging: hv: Repl... |
88 |
.b = { |
39c4e9c37 Staging: hv: Add ... |
89 90 91 92 |
0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf } }, |
9153f7b99 staging: hv: Adde... |
93 94 95 |
/* {57164f39-9115-4e78-ab55-382f3bd5422d} */ /* Heartbeat */ { |
358d2ee2e Staging: hv: Repl... |
96 |
.b = { |
9153f7b99 staging: hv: Adde... |
97 98 99 100 |
0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d } }, |
245ba56a5 Staging: hv: Impl... |
101 102 103 |
/* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */ /* KVP */ { |
358d2ee2e Staging: hv: Repl... |
104 |
.b = { |
245ba56a5 Staging: hv: Impl... |
105 106 107 108 |
0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6 } }, |
3e7ee4902 Staging: hv: add ... |
109 |
}; |
c88c4e4c7 Staging: hv: Adde... |
110 111 |
/** |
da0e96315 hv: rename prep_n... |
112 |
* vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message |
c88c4e4c7 Staging: hv: Adde... |
113 114 115 116 117 118 119 120 121 122 123 124 125 |
* @icmsghdrp: Pointer to msg header structure * @icmsg_negotiate: Pointer to negotiate message structure * @buf: Raw buffer channel data * * @icmsghdrp is of type &struct icmsg_hdr. * @negop is of type &struct icmsg_negotiate. * Set up and fill in default negotiate response message. This response can * come from both the vmbus driver and the hv_utils driver. The current api * will respond properly to both Windows 2008 and Windows 2008-R2 operating * systems. * * Mainly used by Hyper-V drivers. */ |
da0e96315 hv: rename prep_n... |
126 127 |
void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, struct icmsg_negotiate *negop, u8 *buf) |
c88c4e4c7 Staging: hv: Adde... |
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
{ if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { icmsghdrp->icmsgsize = 0x10; negop = (struct icmsg_negotiate *)&buf[ sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; if (negop->icframe_vercnt == 2 && negop->icversion_data[1].major == 3) { negop->icversion_data[0].major = 3; negop->icversion_data[0].minor = 0; negop->icversion_data[1].major = 3; negop->icversion_data[1].minor = 0; } else { negop->icversion_data[0].major = 1; negop->icversion_data[0].minor = 0; negop->icversion_data[1].major = 1; negop->icversion_data[1].minor = 0; } negop->icframe_vercnt = 1; negop->icmsg_vercnt = 1; } } |
da0e96315 hv: rename prep_n... |
153 |
EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); |
c88c4e4c7 Staging: hv: Adde... |
154 |
|
3e1895195 staging: hv: Corr... |
155 |
/* |
e98cb2768 staging: hv: Conv... |
156 |
* alloc_channel - Allocate and initialize a vmbus channel object |
bd60c33e7 Staging: hv: codi... |
157 |
*/ |
50fe56d24 Staging: hv: make... |
158 |
static struct vmbus_channel *alloc_channel(void) |
3e7ee4902 Staging: hv: add ... |
159 |
{ |
aded7165f Staging: hv: clea... |
160 |
struct vmbus_channel *channel; |
3e7ee4902 Staging: hv: add ... |
161 |
|
aded7165f Staging: hv: clea... |
162 |
channel = kzalloc(sizeof(*channel), GFP_ATOMIC); |
3e7ee4902 Staging: hv: add ... |
163 |
if (!channel) |
3e7ee4902 Staging: hv: add ... |
164 |
return NULL; |
3e7ee4902 Staging: hv: add ... |
165 |
|
54411c425 Staging: hv: make... |
166 |
spin_lock_init(&channel->inbound_lock); |
3e7ee4902 Staging: hv: add ... |
167 |
|
c50f7fb28 staging: hv: Conv... |
168 169 |
channel->controlwq = create_workqueue("hv_vmbus_ctl"); if (!channel->controlwq) { |
8c69f52ab Staging: hv: osd:... |
170 |
kfree(channel); |
3e7ee4902 Staging: hv: add ... |
171 172 173 174 175 |
return NULL; } return channel; } |
3e1895195 staging: hv: Corr... |
176 |
/* |
e98cb2768 staging: hv: Conv... |
177 |
* release_hannel - Release the vmbus channel object itself |
bd60c33e7 Staging: hv: codi... |
178 |
*/ |
4b2f9abea staging: hv: conv... |
179 |
static void release_channel(struct work_struct *work) |
3e7ee4902 Staging: hv: add ... |
180 |
{ |
4b2f9abea staging: hv: conv... |
181 182 183 |
struct vmbus_channel *channel = container_of(work, struct vmbus_channel, work); |
3e7ee4902 Staging: hv: add ... |
184 |
|
c50f7fb28 staging: hv: Conv... |
185 |
destroy_workqueue(channel->controlwq); |
3e7ee4902 Staging: hv: add ... |
186 |
|
8c69f52ab Staging: hv: osd:... |
187 |
kfree(channel); |
3e7ee4902 Staging: hv: add ... |
188 |
} |
3e1895195 staging: hv: Corr... |
189 |
/* |
e98cb2768 staging: hv: Conv... |
190 |
* free_channel - Release the resources used by the vmbus channel object |
bd60c33e7 Staging: hv: codi... |
191 |
*/ |
9f3e28e37 hv: remove free_c... |
192 |
static void free_channel(struct vmbus_channel *channel) |
3e7ee4902 Staging: hv: add ... |
193 |
{ |
3e7ee4902 Staging: hv: add ... |
194 |
|
bd60c33e7 Staging: hv: codi... |
195 196 197 198 199 |
/* * We have to release the channel's workqueue/thread in the vmbus's * workqueue/thread context * ie we can't destroy ourselves. */ |
4b2f9abea staging: hv: conv... |
200 |
INIT_WORK(&channel->work, release_channel); |
da9fcb726 staging: hv: Conv... |
201 |
queue_work(vmbus_connection.work_queue, &channel->work); |
3e7ee4902 Staging: hv: add ... |
202 |
} |
8b5d6d3bd staging: hv: Fix ... |
203 |
|
8b5d6d3bd staging: hv: Fix ... |
204 |
|
4b2f9abea staging: hv: conv... |
205 206 207 208 209 210 211 212 213 |
/* * vmbus_process_rescind_offer - * Rescind the offer by initiating a device removal */ static void vmbus_process_rescind_offer(struct work_struct *work) { struct vmbus_channel *channel = container_of(work, struct vmbus_channel, work); |
696453ba2 Staging: hv: vmbu... |
214 |
vmbus_device_unregister(channel->device_obj); |
4b2f9abea staging: hv: conv... |
215 |
} |
8b5d6d3bd staging: hv: Fix ... |
216 |
|
93e5bd06a Drivers: hv: Make... |
217 218 219 220 221 222 223 224 225 226 |
void vmbus_free_channels(void) { struct vmbus_channel *channel; list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { vmbus_device_unregister(channel->device_obj); kfree(channel->device_obj); free_channel(channel); } } |
3e1895195 staging: hv: Corr... |
227 |
/* |
e98cb2768 staging: hv: Conv... |
228 |
* vmbus_process_offer - Process the offer by creating a channel/device |
c88c4e4c7 Staging: hv: Adde... |
229 |
* associated with this offer |
bd60c33e7 Staging: hv: codi... |
230 |
*/ |
4b2f9abea staging: hv: conv... |
231 |
static void vmbus_process_offer(struct work_struct *work) |
3e7ee4902 Staging: hv: add ... |
232 |
{ |
4b2f9abea staging: hv: conv... |
233 234 235 |
struct vmbus_channel *newchannel = container_of(work, struct vmbus_channel, work); |
aded7165f Staging: hv: clea... |
236 |
struct vmbus_channel *channel; |
188963ec7 staging: hv: Conv... |
237 |
bool fnew = true; |
bd60c33e7 Staging: hv: codi... |
238 |
int ret; |
0f5e44ca6 Staging: hv: make... |
239 |
unsigned long flags; |
3e7ee4902 Staging: hv: add ... |
240 |
|
4b2f9abea staging: hv: conv... |
241 242 |
/* The next possible work is rescind handling */ INIT_WORK(&newchannel->work, vmbus_process_rescind_offer); |
454f18a96 Staging: hv: Remo... |
243 |
/* Make sure this is a new offer */ |
15b2f6479 staging: hv: Conv... |
244 |
spin_lock_irqsave(&vmbus_connection.channel_lock, flags); |
3e7ee4902 Staging: hv: add ... |
245 |
|
da9fcb726 staging: hv: Conv... |
246 |
list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { |
358d2ee2e Staging: hv: Repl... |
247 248 249 250 |
if (!uuid_le_cmp(channel->offermsg.offer.if_type, newchannel->offermsg.offer.if_type) && !uuid_le_cmp(channel->offermsg.offer.if_instance, newchannel->offermsg.offer.if_instance)) { |
188963ec7 staging: hv: Conv... |
251 |
fnew = false; |
3e7ee4902 Staging: hv: add ... |
252 253 254 |
break; } } |
188963ec7 staging: hv: Conv... |
255 |
if (fnew) |
c50f7fb28 staging: hv: Conv... |
256 |
list_add_tail(&newchannel->listentry, |
da9fcb726 staging: hv: Conv... |
257 |
&vmbus_connection.chn_list); |
bd60c33e7 Staging: hv: codi... |
258 |
|
15b2f6479 staging: hv: Conv... |
259 |
spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); |
3e7ee4902 Staging: hv: add ... |
260 |
|
188963ec7 staging: hv: Conv... |
261 |
if (!fnew) { |
e98cb2768 staging: hv: Conv... |
262 |
free_channel(newchannel); |
3e7ee4902 Staging: hv: add ... |
263 264 |
return; } |
bd60c33e7 Staging: hv: codi... |
265 266 267 |
/* * Start the process of binding this offer to the driver * We need to set the DeviceObject field before calling |
646f1ea37 staging: hv: Conv... |
268 |
* vmbus_child_dev_add() |
bd60c33e7 Staging: hv: codi... |
269 |
*/ |
f2c730111 Staging: hv: vmbu... |
270 |
newchannel->device_obj = vmbus_device_create( |
767dff685 staging: hv: Conv... |
271 272 |
&newchannel->offermsg.offer.if_type, &newchannel->offermsg.offer.if_instance, |
188963ec7 staging: hv: Conv... |
273 |
newchannel); |
3e7ee4902 Staging: hv: add ... |
274 |
|
454f18a96 Staging: hv: Remo... |
275 276 277 278 279 |
/* * Add the new device to the bus. This will kick off device-driver * binding which eventually invokes the device driver's AddDevice() * method. */ |
227942819 Staging: hv: vmbu... |
280 |
ret = vmbus_device_register(newchannel->device_obj); |
bd60c33e7 Staging: hv: codi... |
281 |
if (ret != 0) { |
0a46618d5 staging: hv: Repl... |
282 283 |
pr_err("unable to add child device object (relid %d) ", |
c50f7fb28 staging: hv: Conv... |
284 |
newchannel->offermsg.child_relid); |
3e7ee4902 Staging: hv: add ... |
285 |
|
15b2f6479 staging: hv: Conv... |
286 |
spin_lock_irqsave(&vmbus_connection.channel_lock, flags); |
c50f7fb28 staging: hv: Conv... |
287 |
list_del(&newchannel->listentry); |
15b2f6479 staging: hv: Conv... |
288 |
spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); |
8b8ee6753 Drivers: hv: Fix ... |
289 |
kfree(newchannel->device_obj); |
3e7ee4902 Staging: hv: add ... |
290 |
|
e98cb2768 staging: hv: Conv... |
291 |
free_channel(newchannel); |
bd60c33e7 Staging: hv: codi... |
292 |
} else { |
454f18a96 Staging: hv: Remo... |
293 294 295 296 297 |
/* * This state is used to indicate a successful open * so that when we do close the channel normally, we * can cleanup properly */ |
c50f7fb28 staging: hv: Conv... |
298 |
newchannel->state = CHANNEL_OPEN_STATE; |
3e7ee4902 Staging: hv: add ... |
299 |
} |
3e7ee4902 Staging: hv: add ... |
300 |
} |
3e1895195 staging: hv: Corr... |
301 |
/* |
e98cb2768 staging: hv: Conv... |
302 |
* vmbus_onoffer - Handler for channel offers from vmbus in parent partition. |
bd60c33e7 Staging: hv: codi... |
303 |
* |
bd60c33e7 Staging: hv: codi... |
304 |
*/ |
e98cb2768 staging: hv: Conv... |
305 |
static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) |
3e7ee4902 Staging: hv: add ... |
306 |
{ |
bd60c33e7 Staging: hv: codi... |
307 |
struct vmbus_channel_offer_channel *offer; |
188963ec7 staging: hv: Conv... |
308 |
struct vmbus_channel *newchannel; |
358d2ee2e Staging: hv: Repl... |
309 310 |
uuid_le *guidtype; uuid_le *guidinstance; |
3e7ee4902 Staging: hv: add ... |
311 |
int i; |
188963ec7 staging: hv: Conv... |
312 |
int fsupported = 0; |
3e7ee4902 Staging: hv: add ... |
313 |
|
bd60c33e7 Staging: hv: codi... |
314 315 |
offer = (struct vmbus_channel_offer_channel *)hdr; for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) { |
358d2ee2e Staging: hv: Repl... |
316 317 |
if (!uuid_le_cmp(offer->offer.if_type, supported_device_classes[i])) { |
188963ec7 staging: hv: Conv... |
318 |
fsupported = 1; |
3e7ee4902 Staging: hv: add ... |
319 320 321 |
break; } } |
98e087022 staging: hv: Remo... |
322 |
if (!fsupported) |
3e7ee4902 Staging: hv: add ... |
323 |
return; |
3e7ee4902 Staging: hv: add ... |
324 |
|
767dff685 staging: hv: Conv... |
325 326 |
guidtype = &offer->offer.if_type; guidinstance = &offer->offer.if_instance; |
3e7ee4902 Staging: hv: add ... |
327 |
|
454f18a96 Staging: hv: Remo... |
328 |
/* Allocate the channel object and save this offer. */ |
e98cb2768 staging: hv: Conv... |
329 |
newchannel = alloc_channel(); |
188963ec7 staging: hv: Conv... |
330 |
if (!newchannel) { |
0a46618d5 staging: hv: Repl... |
331 332 |
pr_err("Unable to allocate channel object "); |
3e7ee4902 Staging: hv: add ... |
333 334 |
return; } |
c50f7fb28 staging: hv: Conv... |
335 |
memcpy(&newchannel->offermsg, offer, |
bd60c33e7 Staging: hv: codi... |
336 |
sizeof(struct vmbus_channel_offer_channel)); |
c50f7fb28 staging: hv: Conv... |
337 338 |
newchannel->monitor_grp = (u8)offer->monitorid / 32; newchannel->monitor_bit = (u8)offer->monitorid % 32; |
3e7ee4902 Staging: hv: add ... |
339 |
|
4b2f9abea staging: hv: conv... |
340 341 |
INIT_WORK(&newchannel->work, vmbus_process_offer); queue_work(newchannel->controlwq, &newchannel->work); |
3e7ee4902 Staging: hv: add ... |
342 |
} |
3e1895195 staging: hv: Corr... |
343 |
/* |
e98cb2768 staging: hv: Conv... |
344 |
* vmbus_onoffer_rescind - Rescind offer handler. |
bd60c33e7 Staging: hv: codi... |
345 346 347 |
* * We queue a work item to process this offer synchronously */ |
e98cb2768 staging: hv: Conv... |
348 |
static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) |
3e7ee4902 Staging: hv: add ... |
349 |
{ |
bd60c33e7 Staging: hv: codi... |
350 |
struct vmbus_channel_rescind_offer *rescind; |
aded7165f Staging: hv: clea... |
351 |
struct vmbus_channel *channel; |
3e7ee4902 Staging: hv: add ... |
352 |
|
bd60c33e7 Staging: hv: codi... |
353 |
rescind = (struct vmbus_channel_rescind_offer *)hdr; |
c69776771 staging: hv: Conv... |
354 |
channel = relid2channel(rescind->child_relid); |
98e087022 staging: hv: Remo... |
355 356 357 |
if (channel == NULL) /* Just return here, no channel found */ |
3e7ee4902 Staging: hv: add ... |
358 |
return; |
3e7ee4902 Staging: hv: add ... |
359 |
|
4b2f9abea staging: hv: conv... |
360 361 362 |
/* work is initialized for vmbus_process_rescind_offer() from * vmbus_process_offer() where the channel got created */ queue_work(channel->controlwq, &channel->work); |
3e7ee4902 Staging: hv: add ... |
363 |
} |
3e1895195 staging: hv: Corr... |
364 |
/* |
e98cb2768 staging: hv: Conv... |
365 366 |
* vmbus_onoffers_delivered - * This is invoked when all offers have been delivered. |
bd60c33e7 Staging: hv: codi... |
367 368 369 |
* * Nothing to do here. */ |
e98cb2768 staging: hv: Conv... |
370 |
static void vmbus_onoffers_delivered( |
bd60c33e7 Staging: hv: codi... |
371 |
struct vmbus_channel_message_header *hdr) |
3e7ee4902 Staging: hv: add ... |
372 |
{ |
3e7ee4902 Staging: hv: add ... |
373 |
} |
3e1895195 staging: hv: Corr... |
374 |
/* |
e98cb2768 staging: hv: Conv... |
375 |
* vmbus_onopen_result - Open result handler. |
bd60c33e7 Staging: hv: codi... |
376 377 378 379 380 |
* * This is invoked when we received a response to our channel open request. * Find the matching request, copy the response and signal the requesting * thread. */ |
e98cb2768 staging: hv: Conv... |
381 |
static void vmbus_onopen_result(struct vmbus_channel_message_header *hdr) |
3e7ee4902 Staging: hv: add ... |
382 |
{ |
bd60c33e7 Staging: hv: codi... |
383 |
struct vmbus_channel_open_result *result; |
188963ec7 staging: hv: Conv... |
384 385 386 |
struct vmbus_channel_msginfo *msginfo; struct vmbus_channel_message_header *requestheader; struct vmbus_channel_open_channel *openmsg; |
dd0813b6f Staging: hv: make... |
387 |
unsigned long flags; |
3e7ee4902 Staging: hv: add ... |
388 |
|
bd60c33e7 Staging: hv: codi... |
389 |
result = (struct vmbus_channel_open_result *)hdr; |
3e7ee4902 Staging: hv: add ... |
390 |
|
bd60c33e7 Staging: hv: codi... |
391 392 393 |
/* * Find the open msg, copy the result and signal/unblock the wait event */ |
15b2f6479 staging: hv: Conv... |
394 |
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); |
3e7ee4902 Staging: hv: add ... |
395 |
|
ebb61e5f9 Staging: hv: Fixe... |
396 397 |
list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, msglistentry) { |
188963ec7 staging: hv: Conv... |
398 |
requestheader = |
c50f7fb28 staging: hv: Conv... |
399 |
(struct vmbus_channel_message_header *)msginfo->msg; |
188963ec7 staging: hv: Conv... |
400 |
|
c50f7fb28 staging: hv: Conv... |
401 |
if (requestheader->msgtype == CHANNELMSG_OPENCHANNEL) { |
188963ec7 staging: hv: Conv... |
402 |
openmsg = |
c50f7fb28 staging: hv: Conv... |
403 404 405 406 |
(struct vmbus_channel_open_channel *)msginfo->msg; if (openmsg->child_relid == result->child_relid && openmsg->openid == result->openid) { memcpy(&msginfo->response.open_result, |
bd60c33e7 Staging: hv: codi... |
407 |
result, |
9568a1931 Staging: hv: Use ... |
408 409 410 |
sizeof( struct vmbus_channel_open_result)); complete(&msginfo->waitevent); |
3e7ee4902 Staging: hv: add ... |
411 412 413 414 |
break; } } } |
15b2f6479 staging: hv: Conv... |
415 |
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); |
3e7ee4902 Staging: hv: add ... |
416 |
} |
3e1895195 staging: hv: Corr... |
417 |
/* |
e98cb2768 staging: hv: Conv... |
418 |
* vmbus_ongpadl_created - GPADL created handler. |
bd60c33e7 Staging: hv: codi... |
419 420 421 422 423 |
* * This is invoked when we received a response to our gpadl create request. * Find the matching request, copy the response and signal the requesting * thread. */ |
e98cb2768 staging: hv: Conv... |
424 |
static void vmbus_ongpadl_created(struct vmbus_channel_message_header *hdr) |
3e7ee4902 Staging: hv: add ... |
425 |
{ |
188963ec7 staging: hv: Conv... |
426 |
struct vmbus_channel_gpadl_created *gpadlcreated; |
188963ec7 staging: hv: Conv... |
427 428 429 |
struct vmbus_channel_msginfo *msginfo; struct vmbus_channel_message_header *requestheader; struct vmbus_channel_gpadl_header *gpadlheader; |
dd0813b6f Staging: hv: make... |
430 |
unsigned long flags; |
3e7ee4902 Staging: hv: add ... |
431 |
|
188963ec7 staging: hv: Conv... |
432 |
gpadlcreated = (struct vmbus_channel_gpadl_created *)hdr; |
3e7ee4902 Staging: hv: add ... |
433 |
|
bd60c33e7 Staging: hv: codi... |
434 435 436 437 |
/* * Find the establish msg, copy the result and signal/unblock the wait * event */ |
15b2f6479 staging: hv: Conv... |
438 |
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); |
3e7ee4902 Staging: hv: add ... |
439 |
|
ebb61e5f9 Staging: hv: Fixe... |
440 441 |
list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, msglistentry) { |
188963ec7 staging: hv: Conv... |
442 |
requestheader = |
c50f7fb28 staging: hv: Conv... |
443 |
(struct vmbus_channel_message_header *)msginfo->msg; |
188963ec7 staging: hv: Conv... |
444 |
|
c50f7fb28 staging: hv: Conv... |
445 |
if (requestheader->msgtype == CHANNELMSG_GPADL_HEADER) { |
188963ec7 staging: hv: Conv... |
446 447 |
gpadlheader = (struct vmbus_channel_gpadl_header *)requestheader; |
c50f7fb28 staging: hv: Conv... |
448 449 450 451 |
if ((gpadlcreated->child_relid == gpadlheader->child_relid) && (gpadlcreated->gpadl == gpadlheader->gpadl)) { memcpy(&msginfo->response.gpadl_created, |
188963ec7 staging: hv: Conv... |
452 |
gpadlcreated, |
9568a1931 Staging: hv: Use ... |
453 454 455 |
sizeof( struct vmbus_channel_gpadl_created)); complete(&msginfo->waitevent); |
3e7ee4902 Staging: hv: add ... |
456 457 458 459 |
break; } } } |
15b2f6479 staging: hv: Conv... |
460 |
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); |
3e7ee4902 Staging: hv: add ... |
461 |
} |
3e1895195 staging: hv: Corr... |
462 |
/* |
e98cb2768 staging: hv: Conv... |
463 |
* vmbus_ongpadl_torndown - GPADL torndown handler. |
bd60c33e7 Staging: hv: codi... |
464 465 466 467 468 |
* * This is invoked when we received a response to our gpadl teardown request. * Find the matching request, copy the response and signal the requesting * thread. */ |
e98cb2768 staging: hv: Conv... |
469 |
static void vmbus_ongpadl_torndown( |
bd60c33e7 Staging: hv: codi... |
470 |
struct vmbus_channel_message_header *hdr) |
3e7ee4902 Staging: hv: add ... |
471 |
{ |
188963ec7 staging: hv: Conv... |
472 |
struct vmbus_channel_gpadl_torndown *gpadl_torndown; |
188963ec7 staging: hv: Conv... |
473 474 475 |
struct vmbus_channel_msginfo *msginfo; struct vmbus_channel_message_header *requestheader; struct vmbus_channel_gpadl_teardown *gpadl_teardown; |
dd0813b6f Staging: hv: make... |
476 |
unsigned long flags; |
3e7ee4902 Staging: hv: add ... |
477 |
|
188963ec7 staging: hv: Conv... |
478 |
gpadl_torndown = (struct vmbus_channel_gpadl_torndown *)hdr; |
bd60c33e7 Staging: hv: codi... |
479 480 481 482 |
/* * Find the open msg, copy the result and signal/unblock the wait event */ |
15b2f6479 staging: hv: Conv... |
483 |
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); |
3e7ee4902 Staging: hv: add ... |
484 |
|
ebb61e5f9 Staging: hv: Fixe... |
485 486 |
list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, msglistentry) { |
188963ec7 staging: hv: Conv... |
487 |
requestheader = |
c50f7fb28 staging: hv: Conv... |
488 |
(struct vmbus_channel_message_header *)msginfo->msg; |
3e7ee4902 Staging: hv: add ... |
489 |
|
c50f7fb28 staging: hv: Conv... |
490 |
if (requestheader->msgtype == CHANNELMSG_GPADL_TEARDOWN) { |
188963ec7 staging: hv: Conv... |
491 492 |
gpadl_teardown = (struct vmbus_channel_gpadl_teardown *)requestheader; |
3e7ee4902 Staging: hv: add ... |
493 |
|
c50f7fb28 staging: hv: Conv... |
494 495 |
if (gpadl_torndown->gpadl == gpadl_teardown->gpadl) { memcpy(&msginfo->response.gpadl_torndown, |
188963ec7 staging: hv: Conv... |
496 |
gpadl_torndown, |
9568a1931 Staging: hv: Use ... |
497 498 499 |
sizeof( struct vmbus_channel_gpadl_torndown)); complete(&msginfo->waitevent); |
3e7ee4902 Staging: hv: add ... |
500 501 502 503 |
break; } } } |
15b2f6479 staging: hv: Conv... |
504 |
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); |
3e7ee4902 Staging: hv: add ... |
505 |
} |
3e1895195 staging: hv: Corr... |
506 |
/* |
e98cb2768 staging: hv: Conv... |
507 |
* vmbus_onversion_response - Version response handler |
bd60c33e7 Staging: hv: codi... |
508 509 510 511 512 |
* * This is invoked when we received a response to our initiate contact request. * Find the matching request, copy the response and signal the requesting * thread. */ |
e98cb2768 staging: hv: Conv... |
513 |
static void vmbus_onversion_response( |
bd60c33e7 Staging: hv: codi... |
514 |
struct vmbus_channel_message_header *hdr) |
3e7ee4902 Staging: hv: add ... |
515 |
{ |
188963ec7 staging: hv: Conv... |
516 517 |
struct vmbus_channel_msginfo *msginfo; struct vmbus_channel_message_header *requestheader; |
82250213d Staging: hv: type... |
518 |
struct vmbus_channel_initiate_contact *initiate; |
188963ec7 staging: hv: Conv... |
519 |
struct vmbus_channel_version_response *version_response; |
dd0813b6f Staging: hv: make... |
520 |
unsigned long flags; |
3e7ee4902 Staging: hv: add ... |
521 |
|
188963ec7 staging: hv: Conv... |
522 |
version_response = (struct vmbus_channel_version_response *)hdr; |
15b2f6479 staging: hv: Conv... |
523 |
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); |
3e7ee4902 Staging: hv: add ... |
524 |
|
ebb61e5f9 Staging: hv: Fixe... |
525 526 |
list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, msglistentry) { |
188963ec7 staging: hv: Conv... |
527 |
requestheader = |
c50f7fb28 staging: hv: Conv... |
528 |
(struct vmbus_channel_message_header *)msginfo->msg; |
3e7ee4902 Staging: hv: add ... |
529 |
|
c50f7fb28 staging: hv: Conv... |
530 531 |
if (requestheader->msgtype == CHANNELMSG_INITIATE_CONTACT) { |
188963ec7 staging: hv: Conv... |
532 533 |
initiate = (struct vmbus_channel_initiate_contact *)requestheader; |
c50f7fb28 staging: hv: Conv... |
534 |
memcpy(&msginfo->response.version_response, |
188963ec7 staging: hv: Conv... |
535 |
version_response, |
bd60c33e7 Staging: hv: codi... |
536 |
sizeof(struct vmbus_channel_version_response)); |
9568a1931 Staging: hv: Use ... |
537 |
complete(&msginfo->waitevent); |
3e7ee4902 Staging: hv: add ... |
538 539 |
} } |
15b2f6479 staging: hv: Conv... |
540 |
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); |
3e7ee4902 Staging: hv: add ... |
541 |
} |
c8212f04d Staging: hv: reor... |
542 543 |
/* Channel message dispatch table */ static struct vmbus_channel_message_table_entry |
b7c6b02f3 Staging: hv: vmbu... |
544 |
channel_message_table[CHANNELMSG_COUNT] = { |
c50f7fb28 staging: hv: Conv... |
545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 |
{CHANNELMSG_INVALID, NULL}, {CHANNELMSG_OFFERCHANNEL, vmbus_onoffer}, {CHANNELMSG_RESCIND_CHANNELOFFER, vmbus_onoffer_rescind}, {CHANNELMSG_REQUESTOFFERS, NULL}, {CHANNELMSG_ALLOFFERS_DELIVERED, vmbus_onoffers_delivered}, {CHANNELMSG_OPENCHANNEL, NULL}, {CHANNELMSG_OPENCHANNEL_RESULT, vmbus_onopen_result}, {CHANNELMSG_CLOSECHANNEL, NULL}, {CHANNELMSG_GPADL_HEADER, NULL}, {CHANNELMSG_GPADL_BODY, NULL}, {CHANNELMSG_GPADL_CREATED, vmbus_ongpadl_created}, {CHANNELMSG_GPADL_TEARDOWN, NULL}, {CHANNELMSG_GPADL_TORNDOWN, vmbus_ongpadl_torndown}, {CHANNELMSG_RELID_RELEASED, NULL}, {CHANNELMSG_INITIATE_CONTACT, NULL}, {CHANNELMSG_VERSION_RESPONSE, vmbus_onversion_response}, {CHANNELMSG_UNLOAD, NULL}, |
c8212f04d Staging: hv: reor... |
562 |
}; |
3e1895195 staging: hv: Corr... |
563 |
/* |
e98cb2768 staging: hv: Conv... |
564 |
* vmbus_onmessage - Handler for channel protocol messages. |
bd60c33e7 Staging: hv: codi... |
565 566 567 |
* * This is invoked in the vmbus worker thread context. */ |
e98cb2768 staging: hv: Conv... |
568 |
void vmbus_onmessage(void *context) |
3e7ee4902 Staging: hv: add ... |
569 |
{ |
188963ec7 staging: hv: Conv... |
570 |
struct hv_message *msg = context; |
82250213d Staging: hv: type... |
571 |
struct vmbus_channel_message_header *hdr; |
3e7ee4902 Staging: hv: add ... |
572 |
int size; |
f6feebe07 staging: hv: Conv... |
573 574 |
hdr = (struct vmbus_channel_message_header *)msg->u.payload; size = msg->header.payload_size; |
3e7ee4902 Staging: hv: add ... |
575 |
|
c50f7fb28 staging: hv: Conv... |
576 |
if (hdr->msgtype >= CHANNELMSG_COUNT) { |
0a46618d5 staging: hv: Repl... |
577 578 |
pr_err("Received invalid channel message type %d size %d ", |
c50f7fb28 staging: hv: Conv... |
579 |
hdr->msgtype, size); |
04f50c4d2 Staging: hv: osd:... |
580 |
print_hex_dump_bytes("", DUMP_PREFIX_NONE, |
f6feebe07 staging: hv: Conv... |
581 |
(unsigned char *)msg->u.payload, size); |
3e7ee4902 Staging: hv: add ... |
582 583 |
return; } |
b7c6b02f3 Staging: hv: vmbu... |
584 585 |
if (channel_message_table[hdr->msgtype].message_handler) channel_message_table[hdr->msgtype].message_handler(hdr); |
3e7ee4902 Staging: hv: add ... |
586 |
else |
0a46618d5 staging: hv: Repl... |
587 588 |
pr_err("Unhandled channel message type %d ", hdr->msgtype); |
3e7ee4902 Staging: hv: add ... |
589 |
} |
3e1895195 staging: hv: Corr... |
590 |
/* |
e98cb2768 staging: hv: Conv... |
591 |
* vmbus_request_offers - Send a request to get all our pending offers. |
bd60c33e7 Staging: hv: codi... |
592 |
*/ |
e98cb2768 staging: hv: Conv... |
593 |
int vmbus_request_offers(void) |
3e7ee4902 Staging: hv: add ... |
594 |
{ |
82250213d Staging: hv: type... |
595 |
struct vmbus_channel_message_header *msg; |
188963ec7 staging: hv: Conv... |
596 |
struct vmbus_channel_msginfo *msginfo; |
9568a1931 Staging: hv: Use ... |
597 |
int ret, t; |
3e7ee4902 Staging: hv: add ... |
598 |
|
188963ec7 staging: hv: Conv... |
599 |
msginfo = kmalloc(sizeof(*msginfo) + |
bd60c33e7 Staging: hv: codi... |
600 601 |
sizeof(struct vmbus_channel_message_header), GFP_KERNEL); |
188963ec7 staging: hv: Conv... |
602 |
if (!msginfo) |
75910f236 Staging: hv: remo... |
603 |
return -ENOMEM; |
3e7ee4902 Staging: hv: add ... |
604 |
|
9568a1931 Staging: hv: Use ... |
605 |
init_completion(&msginfo->waitevent); |
75910f236 Staging: hv: remo... |
606 |
|
c50f7fb28 staging: hv: Conv... |
607 |
msg = (struct vmbus_channel_message_header *)msginfo->msg; |
3e7ee4902 Staging: hv: add ... |
608 |
|
c50f7fb28 staging: hv: Conv... |
609 |
msg->msgtype = CHANNELMSG_REQUESTOFFERS; |
3e7ee4902 Staging: hv: add ... |
610 |
|
3e7ee4902 Staging: hv: add ... |
611 |
|
c69776771 staging: hv: Conv... |
612 |
ret = vmbus_post_msg(msg, |
bd60c33e7 Staging: hv: codi... |
613 614 |
sizeof(struct vmbus_channel_message_header)); if (ret != 0) { |
0a46618d5 staging: hv: Repl... |
615 616 |
pr_err("Unable to request offers - %d ", ret); |
3e7ee4902 Staging: hv: add ... |
617 |
|
0c3b7b2f7 Staging: hv: Use ... |
618 619 |
goto cleanup; } |
3e7ee4902 Staging: hv: add ... |
620 |
|
2dfde9644 Staging: hv: vmbu... |
621 |
t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ); |
9568a1931 Staging: hv: Use ... |
622 |
if (t == 0) { |
0c3b7b2f7 Staging: hv: Use ... |
623 624 |
ret = -ETIMEDOUT; goto cleanup; |
3e7ee4902 Staging: hv: add ... |
625 |
} |
3e7ee4902 Staging: hv: add ... |
626 |
|
3e7ee4902 Staging: hv: add ... |
627 |
|
0c3b7b2f7 Staging: hv: Use ... |
628 |
cleanup: |
dd9b15dc0 staging: hv: Remo... |
629 |
kfree(msginfo); |
3e7ee4902 Staging: hv: add ... |
630 |
|
3e7ee4902 Staging: hv: add ... |
631 632 |
return ret; } |
454f18a96 Staging: hv: Remo... |
633 |
/* eof */ |