Staging: hv: fix up typedefs in NetVscApi.h
[deliverable/linux.git] / drivers / staging / hv / StorVsc.c
CommitLineData
bef4a34a
HJ
1/*
2 *
3 * Copyright (c) 2009, Microsoft Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 *
18 * Authors:
19 * Haiyang Zhang <haiyangz@microsoft.com>
20 * Hank Janssen <hjanssen@microsoft.com>
21 *
22 */
23
5654e932 24#include <linux/kernel.h>
0ffa63b0
GKH
25#include <linux/string.h>
26#include <linux/mm.h>
b4362c9c 27#include <linux/delay.h>
4983b39a 28#include "osd.h"
97f4ee3d 29#include "include/logging.h"
97f4ee3d
GKH
30#include "include/StorVscApi.h"
31#include "include/VmbusPacketFormat.h"
32#include "include/vstorage.h"
bef4a34a
HJ
33
34
bef4a34a 35
454f18a9
BP
36/* #defines */
37
38
39
40/* Data types */
41
bef4a34a
HJ
42
43typedef struct _STORVSC_REQUEST_EXTENSION {
454f18a9 44 /* LIST_ENTRY ListEntry; */
bef4a34a 45
0b3f6834 46 struct hv_storvsc_request *Request;
3d3b5518 47 struct hv_device *Device;
bef4a34a 48
454f18a9 49 /* Synchronize the request/response if needed */
aedb444a 50 struct osd_waitevent *WaitEvent;
bef4a34a
HJ
51
52 VSTOR_PACKET VStorPacket;
53} STORVSC_REQUEST_EXTENSION;
54
55
454f18a9 56/* A storvsc device is a device object that contains a vmbus channel */
bef4a34a 57typedef struct _STORVSC_DEVICE{
3d3b5518 58 struct hv_device *Device;
bef4a34a 59
f4888417 60 atomic_t RefCount; /* 0 indicates the device is being destroyed */
bef4a34a 61
f4888417 62 atomic_t NumOutstandingRequests;
bef4a34a 63
454f18a9
BP
64 /*
65 * Each unique Port/Path/Target represents 1 channel ie scsi
66 * controller. In reality, the pathid, targetid is always 0
67 * and the port is set by us
68 */
3abcbc45 69 unsigned int PortNumber;
59471438
GKH
70 unsigned char PathId;
71 unsigned char TargetId;
bef4a34a 72
454f18a9
BP
73 /* LIST_ENTRY OutstandingRequestList; */
74 /* HANDLE OutstandingRequestLock; */
bef4a34a 75
454f18a9 76 /* Used for vsc/vsp channel reset process */
bef4a34a
HJ
77 STORVSC_REQUEST_EXTENSION InitRequest;
78
79 STORVSC_REQUEST_EXTENSION ResetRequest;
80
81} STORVSC_DEVICE;
82
83
454f18a9
BP
84
85/* Globals */
86
bef4a34a
HJ
87static const char* gDriverName="storvsc";
88
454f18a9 89/* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
caf26a31
GKH
90static const struct hv_guid gStorVscDeviceType = {
91 .data = {
92 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
93 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f
94 }
bef4a34a
HJ
95};
96
454f18a9
BP
97
98/* Internal routines */
99
bef4a34a
HJ
100static int
101StorVscOnDeviceAdd(
3d3b5518 102 struct hv_device *Device,
bef4a34a
HJ
103 void *AdditionalInfo
104 );
105
106static int
107StorVscOnDeviceRemove(
3d3b5518 108 struct hv_device *Device
bef4a34a
HJ
109 );
110
111static int
112StorVscOnIORequest(
3d3b5518 113 struct hv_device *Device,
0b3f6834 114 struct hv_storvsc_request *Request
bef4a34a
HJ
115 );
116
117static int
118StorVscOnHostReset(
3d3b5518 119 struct hv_device *Device
bef4a34a
HJ
120 );
121
122static void
123StorVscOnCleanup(
775ef25e 124 struct hv_driver *Device
bef4a34a
HJ
125 );
126
127static void
128StorVscOnChannelCallback(
8282c400 129 void * Context
bef4a34a
HJ
130 );
131
132static void
133StorVscOnIOCompletion(
3d3b5518 134 struct hv_device *Device,
bef4a34a
HJ
135 VSTOR_PACKET *VStorPacket,
136 STORVSC_REQUEST_EXTENSION *RequestExt
137 );
138
139static void
140StorVscOnReceive(
3d3b5518 141 struct hv_device *Device,
bef4a34a
HJ
142 VSTOR_PACKET *VStorPacket,
143 STORVSC_REQUEST_EXTENSION *RequestExt
144 );
145
146static int
147StorVscConnectToVsp(
3d3b5518 148 struct hv_device *Device
bef4a34a
HJ
149 );
150
3d3b5518 151static inline STORVSC_DEVICE* AllocStorDevice(struct hv_device *Device)
bef4a34a
HJ
152{
153 STORVSC_DEVICE *storDevice;
154
e276a3a5 155 storDevice = kzalloc(sizeof(STORVSC_DEVICE), GFP_KERNEL);
bef4a34a
HJ
156 if (!storDevice)
157 return NULL;
158
454f18a9
BP
159 /* Set to 2 to allow both inbound and outbound traffics */
160 /* (ie GetStorDevice() and MustGetStorDevice()) to proceed. */
f4888417 161 atomic_cmpxchg(&storDevice->RefCount, 0, 2);
bef4a34a
HJ
162
163 storDevice->Device = Device;
164 Device->Extension = storDevice;
165
166 return storDevice;
167}
168
169static inline void FreeStorDevice(STORVSC_DEVICE *Device)
170{
f4888417 171 ASSERT( atomic_read(&Device->RefCount) == 0);
8c69f52a 172 kfree(Device);
bef4a34a
HJ
173}
174
454f18a9 175/* Get the stordevice object iff exists and its refcount > 1 */
3d3b5518 176static inline STORVSC_DEVICE* GetStorDevice(struct hv_device *Device)
bef4a34a
HJ
177{
178 STORVSC_DEVICE *storDevice;
179
180 storDevice = (STORVSC_DEVICE*)Device->Extension;
f4888417
BP
181 if (storDevice && atomic_read(&storDevice->RefCount) > 1)
182 atomic_inc(&storDevice->RefCount);
bef4a34a 183 else
bef4a34a 184 storDevice = NULL;
bef4a34a
HJ
185
186 return storDevice;
187}
188
454f18a9 189/* Get the stordevice object iff exists and its refcount > 0 */
3d3b5518 190static inline STORVSC_DEVICE* MustGetStorDevice(struct hv_device *Device)
bef4a34a
HJ
191{
192 STORVSC_DEVICE *storDevice;
193
194 storDevice = (STORVSC_DEVICE*)Device->Extension;
f4888417
BP
195 if (storDevice && atomic_read(&storDevice->RefCount))
196 atomic_inc(&storDevice->RefCount);
bef4a34a 197 else
bef4a34a 198 storDevice = NULL;
bef4a34a
HJ
199
200 return storDevice;
201}
202
3d3b5518 203static inline void PutStorDevice(struct hv_device *Device)
bef4a34a
HJ
204{
205 STORVSC_DEVICE *storDevice;
206
207 storDevice = (STORVSC_DEVICE*)Device->Extension;
208 ASSERT(storDevice);
209
f4888417
BP
210 atomic_dec(&storDevice->RefCount);
211 ASSERT(atomic_read(&storDevice->RefCount));
bef4a34a
HJ
212}
213
454f18a9 214/* Drop ref count to 1 to effectively disable GetStorDevice() */
3d3b5518 215static inline STORVSC_DEVICE* ReleaseStorDevice(struct hv_device *Device)
bef4a34a
HJ
216{
217 STORVSC_DEVICE *storDevice;
218
219 storDevice = (STORVSC_DEVICE*)Device->Extension;
220 ASSERT(storDevice);
221
454f18a9 222 /* Busy wait until the ref drop to 2, then set it to 1 */
f4888417 223 while (atomic_cmpxchg(&storDevice->RefCount, 2, 1) != 2)
bef4a34a 224 {
b4362c9c 225 udelay(100);
bef4a34a
HJ
226 }
227
228 return storDevice;
229}
230
454f18a9 231/* Drop ref count to 0. No one can use StorDevice object. */
3d3b5518 232static inline STORVSC_DEVICE* FinalReleaseStorDevice(struct hv_device *Device)
bef4a34a
HJ
233{
234 STORVSC_DEVICE *storDevice;
235
236 storDevice = (STORVSC_DEVICE*)Device->Extension;
237 ASSERT(storDevice);
238
454f18a9 239 /* Busy wait until the ref drop to 1, then set it to 0 */
f4888417 240 while (atomic_cmpxchg(&storDevice->RefCount, 1, 0) != 1)
bef4a34a 241 {
b4362c9c 242 udelay(100);
bef4a34a
HJ
243 }
244
245 Device->Extension = NULL;
246 return storDevice;
247}
248
249/*++;
250
251
252Name:
253 StorVscInitialize()
254
255Description:
256 Main entry point
257
258--*/
259int
260StorVscInitialize(
775ef25e 261 struct hv_driver *Driver
bef4a34a
HJ
262 )
263{
264 STORVSC_DRIVER_OBJECT* storDriver = (STORVSC_DRIVER_OBJECT*)Driver;
265 int ret=0;
266
267 DPRINT_ENTER(STORVSC);
268
b7d7ae6f 269 DPRINT_DBG(STORVSC, "sizeof(STORVSC_REQUEST)=%zd sizeof(STORVSC_REQUEST_EXTENSION)=%zd sizeof(VSTOR_PACKET)=%zd, sizeof(VMSCSI_REQUEST)=%zd",
0b3f6834 270 sizeof(struct hv_storvsc_request), sizeof(STORVSC_REQUEST_EXTENSION), sizeof(VSTOR_PACKET), sizeof(VMSCSI_REQUEST));
bef4a34a 271
454f18a9 272 /* Make sure we are at least 2 pages since 1 page is used for control */
bef4a34a
HJ
273 ASSERT(storDriver->RingBufferSize >= (PAGE_SIZE << 1));
274
275 Driver->name = gDriverName;
caf26a31 276 memcpy(&Driver->deviceType, &gStorVscDeviceType, sizeof(struct hv_guid));
bef4a34a
HJ
277
278 storDriver->RequestExtSize = sizeof(STORVSC_REQUEST_EXTENSION);
279
454f18a9
BP
280 /*
281 * Divide the ring buffer data size (which is 1 page less
282 * than the ring buffer size since that page is reserved for
283 * the ring buffer indices) by the max request size (which is
284 * VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER + VSTOR_PACKET + u64)
285 */
bef4a34a 286 storDriver->MaxOutstandingRequestsPerChannel =
59471438 287 ((storDriver->RingBufferSize - PAGE_SIZE) / ALIGN_UP(MAX_MULTIPAGE_BUFFER_PACKET + sizeof(VSTOR_PACKET) + sizeof(u64),sizeof(u64)));
bef4a34a
HJ
288
289 DPRINT_INFO(STORVSC, "max io %u, currently %u\n", storDriver->MaxOutstandingRequestsPerChannel, STORVSC_MAX_IO_REQUESTS);
290
454f18a9 291 /* Setup the dispatch table */
bef4a34a
HJ
292 storDriver->Base.OnDeviceAdd = StorVscOnDeviceAdd;
293 storDriver->Base.OnDeviceRemove = StorVscOnDeviceRemove;
294 storDriver->Base.OnCleanup = StorVscOnCleanup;
295
296 storDriver->OnIORequest = StorVscOnIORequest;
297 storDriver->OnHostReset = StorVscOnHostReset;
298
299 DPRINT_EXIT(STORVSC);
300
301 return ret;
302}
303
304/*++
305
306Name:
307 StorVscOnDeviceAdd()
308
309Description:
310 Callback when the device belonging to this driver is added
311
312--*/
bd1de709 313static int
bef4a34a 314StorVscOnDeviceAdd(
3d3b5518 315 struct hv_device *Device,
bef4a34a
HJ
316 void *AdditionalInfo
317 )
318{
319 int ret=0;
320 STORVSC_DEVICE *storDevice;
454f18a9 321 /* VMSTORAGE_CHANNEL_PROPERTIES *props; */
bef4a34a
HJ
322 STORVSC_DEVICE_INFO *deviceInfo = (STORVSC_DEVICE_INFO*)AdditionalInfo;
323
324 DPRINT_ENTER(STORVSC);
325
326 storDevice = AllocStorDevice(Device);
327 if (!storDevice)
328 {
329 ret = -1;
330 goto Cleanup;
331 }
332
454f18a9
BP
333 /* Save the channel properties to our storvsc channel */
334 /* props = (VMSTORAGE_CHANNEL_PROPERTIES*) channel->offerMsg.Offer.u.Standard.UserDefined; */
335
336 /* FIXME: */
337 /*
338 * If we support more than 1 scsi channel, we need to set the
339 * port number here to the scsi channel but how do we get the
340 * scsi channel prior to the bus scan
341 */
bef4a34a 342
454f18a9 343 /* storChannel->PortNumber = 0;
bef4a34a 344 storChannel->PathId = props->PathId;
454f18a9 345 storChannel->TargetId = props->TargetId; */
bef4a34a
HJ
346
347 storDevice->PortNumber = deviceInfo->PortNumber;
454f18a9 348 /* Send it back up */
bef4a34a
HJ
349 ret = StorVscConnectToVsp(Device);
350
454f18a9 351 /* deviceInfo->PortNumber = storDevice->PortNumber; */
bef4a34a
HJ
352 deviceInfo->PathId = storDevice->PathId;
353 deviceInfo->TargetId = storDevice->TargetId;
354
78cd2003 355 DPRINT_DBG(STORVSC, "assigned port %u, path %u target %u\n", storDevice->PortNumber, storDevice->PathId, storDevice->TargetId);
bef4a34a
HJ
356
357Cleanup:
358 DPRINT_EXIT(STORVSC);
359
360 return ret;
361}
362
3d3b5518 363static int StorVscChannelInit(struct hv_device *Device)
bef4a34a
HJ
364{
365 int ret=0;
366 STORVSC_DEVICE *storDevice;
367 STORVSC_REQUEST_EXTENSION *request;
368 VSTOR_PACKET *vstorPacket;
369
370 storDevice = GetStorDevice(Device);
371 if (!storDevice)
372 {
373 DPRINT_ERR(STORVSC, "unable to get stor device...device being destroyed?");
374 DPRINT_EXIT(STORVSC);
375 return -1;
376 }
377
378 request = &storDevice->InitRequest;
379 vstorPacket = &request->VStorPacket;
380
454f18a9 381 /* Now, initiate the vsc/vsp initialization protocol on the open channel */
bef4a34a
HJ
382
383 memset(request, sizeof(STORVSC_REQUEST_EXTENSION), 0);
bfc30aae 384 request->WaitEvent = osd_WaitEventCreate();
bef4a34a
HJ
385
386 vstorPacket->Operation = VStorOperationBeginInitialization;
387 vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
388
389 /*SpinlockAcquire(gDriverExt.packetListLock);
390 INSERT_TAIL_LIST(&gDriverExt.packetList, &packet->listEntry.entry);
391 SpinlockRelease(gDriverExt.packetListLock);*/
392
393 DPRINT_INFO(STORVSC, "BEGIN_INITIALIZATION_OPERATION...");
394
395 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
396 vstorPacket,
397 sizeof(VSTOR_PACKET),
c4b0bc94 398 (unsigned long)request,
bef4a34a
HJ
399 VmbusPacketTypeDataInBand,
400 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
401 if ( ret != 0)
402 {
403 DPRINT_ERR(STORVSC, "unable to send BEGIN_INITIALIZATION_OPERATION");
404 goto Cleanup;
405 }
406
bfc30aae 407 osd_WaitEventWait(request->WaitEvent);
bef4a34a
HJ
408
409 if (vstorPacket->Operation != VStorOperationCompleteIo || vstorPacket->Status != 0)
410 {
78cd2003 411 DPRINT_ERR(STORVSC, "BEGIN_INITIALIZATION_OPERATION failed (op %d status 0x%x)", vstorPacket->Operation, vstorPacket->Status);
bef4a34a
HJ
412 goto Cleanup;
413 }
414
415 DPRINT_INFO(STORVSC, "QUERY_PROTOCOL_VERSION_OPERATION...");
416
454f18a9 417 /* reuse the packet for version range supported */
bef4a34a
HJ
418 memset(vstorPacket, sizeof(VSTOR_PACKET), 0);
419 vstorPacket->Operation = VStorOperationQueryProtocolVersion;
420 vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
421
422 vstorPacket->Version.MajorMinor = VMSTOR_PROTOCOL_VERSION_CURRENT;
423 FILL_VMSTOR_REVISION(vstorPacket->Version.Revision);
424
425 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
426 vstorPacket,
427 sizeof(VSTOR_PACKET),
c4b0bc94 428 (unsigned long)request,
bef4a34a
HJ
429 VmbusPacketTypeDataInBand,
430 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
431 if ( ret != 0)
432 {
433 DPRINT_ERR(STORVSC, "unable to send BEGIN_INITIALIZATION_OPERATION");
434 goto Cleanup;
435 }
436
bfc30aae 437 osd_WaitEventWait(request->WaitEvent);
bef4a34a 438
454f18a9 439 /* TODO: Check returned version */
bef4a34a
HJ
440 if (vstorPacket->Operation != VStorOperationCompleteIo || vstorPacket->Status != 0)
441 {
78cd2003 442 DPRINT_ERR(STORVSC, "QUERY_PROTOCOL_VERSION_OPERATION failed (op %d status 0x%x)", vstorPacket->Operation, vstorPacket->Status);
bef4a34a
HJ
443 goto Cleanup;
444 }
445
454f18a9 446 /* Query channel properties */
bef4a34a
HJ
447 DPRINT_INFO(STORVSC, "QUERY_PROPERTIES_OPERATION...");
448
449 memset(vstorPacket, sizeof(VSTOR_PACKET), 0);
450 vstorPacket->Operation = VStorOperationQueryProperties;
451 vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
452 vstorPacket->StorageChannelProperties.PortNumber = storDevice->PortNumber;
453
454 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
455 vstorPacket,
456 sizeof(VSTOR_PACKET),
c4b0bc94 457 (unsigned long)request,
bef4a34a
HJ
458 VmbusPacketTypeDataInBand,
459 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
460
461 if ( ret != 0)
462 {
463 DPRINT_ERR(STORVSC, "unable to send QUERY_PROPERTIES_OPERATION");
464 goto Cleanup;
465 }
466
bfc30aae 467 osd_WaitEventWait(request->WaitEvent);
bef4a34a 468
454f18a9 469 /* TODO: Check returned version */
bef4a34a
HJ
470 if (vstorPacket->Operation != VStorOperationCompleteIo || vstorPacket->Status != 0)
471 {
78cd2003 472 DPRINT_ERR(STORVSC, "QUERY_PROPERTIES_OPERATION failed (op %d status 0x%x)", vstorPacket->Operation, vstorPacket->Status);
bef4a34a
HJ
473 goto Cleanup;
474 }
475
454f18a9 476 /* storDevice->PortNumber = vstorPacket->StorageChannelProperties.PortNumber; */
bef4a34a
HJ
477 storDevice->PathId = vstorPacket->StorageChannelProperties.PathId;
478 storDevice->TargetId = vstorPacket->StorageChannelProperties.TargetId;
479
78cd2003 480 DPRINT_DBG(STORVSC, "channel flag 0x%x, max xfer len 0x%x", vstorPacket->StorageChannelProperties.Flags, vstorPacket->StorageChannelProperties.MaxTransferBytes);
bef4a34a
HJ
481
482 DPRINT_INFO(STORVSC, "END_INITIALIZATION_OPERATION...");
483
484 memset(vstorPacket, sizeof(VSTOR_PACKET), 0);
485 vstorPacket->Operation = VStorOperationEndInitialization;
486 vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
487
488 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
489 vstorPacket,
490 sizeof(VSTOR_PACKET),
c4b0bc94 491 (unsigned long)request,
bef4a34a
HJ
492 VmbusPacketTypeDataInBand,
493 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
494
495 if ( ret != 0)
496 {
497 DPRINT_ERR(STORVSC, "unable to send END_INITIALIZATION_OPERATION");
498 goto Cleanup;
499 }
500
bfc30aae 501 osd_WaitEventWait(request->WaitEvent);
bef4a34a
HJ
502
503 if (vstorPacket->Operation != VStorOperationCompleteIo || vstorPacket->Status != 0)
504 {
78cd2003 505 DPRINT_ERR(STORVSC, "END_INITIALIZATION_OPERATION failed (op %d status 0x%x)", vstorPacket->Operation, vstorPacket->Status);
bef4a34a
HJ
506 goto Cleanup;
507 }
508
509 DPRINT_INFO(STORVSC, "**** storage channel up and running!! ****");
510
511Cleanup:
512 if (request->WaitEvent)
513 {
420beac4 514 kfree(request->WaitEvent);
bef4a34a
HJ
515 request->WaitEvent = NULL;
516 }
517
518 PutStorDevice(Device);
519
520 DPRINT_EXIT(STORVSC);
521 return ret;
522}
523
524
bd1de709 525static int
bef4a34a 526StorVscConnectToVsp(
3d3b5518 527 struct hv_device *Device
bef4a34a
HJ
528 )
529{
530 int ret=0;
531 VMSTORAGE_CHANNEL_PROPERTIES props;
532
533 STORVSC_DRIVER_OBJECT *storDriver = (STORVSC_DRIVER_OBJECT*) Device->Driver;;
534
535 memset(&props, sizeof(VMSTORAGE_CHANNEL_PROPERTIES), 0);
536
454f18a9 537 /* Open the channel */
bef4a34a
HJ
538 ret = Device->Driver->VmbusChannelInterface.Open(Device,
539 storDriver->RingBufferSize,
540 storDriver->RingBufferSize,
8282c400 541 (void *)&props,
bef4a34a
HJ
542 sizeof(VMSTORAGE_CHANNEL_PROPERTIES),
543 StorVscOnChannelCallback,
544 Device
545 );
546
78cd2003 547 DPRINT_DBG(STORVSC, "storage props: path id %d, tgt id %d, max xfer %d", props.PathId, props.TargetId, props.MaxTransferBytes);
bef4a34a
HJ
548
549 if (ret != 0)
550 {
551 DPRINT_ERR(STORVSC, "unable to open channel: %d", ret);
552 return -1;
553 }
554
555 ret = StorVscChannelInit(Device);
556
557 return ret;
558}
559
560
561/*++
562
563Name:
564 StorVscOnDeviceRemove()
565
566Description:
567 Callback when the our device is being removed
568
569--*/
bd1de709 570static int
bef4a34a 571StorVscOnDeviceRemove(
3d3b5518 572 struct hv_device *Device
bef4a34a
HJ
573 )
574{
575 STORVSC_DEVICE *storDevice;
576 int ret=0;
577
578 DPRINT_ENTER(STORVSC);
579
580 DPRINT_INFO(STORVSC, "disabling storage device (%p)...", Device->Extension);
581
582 storDevice = ReleaseStorDevice(Device);
583
454f18a9
BP
584 /*
585 * At this point, all outbound traffic should be disable. We
586 * only allow inbound traffic (responses) to proceed so that
587 * outstanding requests can be completed.
588 */
f4888417 589 while (atomic_read(&storDevice->NumOutstandingRequests))
bef4a34a 590 {
f4888417 591 DPRINT_INFO(STORVSC, "waiting for %d requests to complete...", atomic_read(&storDevice->NumOutstandingRequests));
bef4a34a 592
b4362c9c 593 udelay(100);
bef4a34a
HJ
594 }
595
596 DPRINT_INFO(STORVSC, "removing storage device (%p)...", Device->Extension);
597
598 storDevice = FinalReleaseStorDevice(Device);
599
600 DPRINT_INFO(STORVSC, "storage device (%p) safe to remove", storDevice);
601
454f18a9 602 /* Close the channel */
bef4a34a
HJ
603 Device->Driver->VmbusChannelInterface.Close(Device);
604
605 FreeStorDevice(storDevice);
606
607 DPRINT_EXIT(STORVSC);
608 return ret;
609}
610
454f18a9
BP
611/* ***************
612static void
613StorVscOnTargetRescan(
614void *Context
615)
616{
3d3b5518 617struct hv_device *device=(struct hv_device *)Context;
454f18a9 618STORVSC_DRIVER_OBJECT *storDriver;
bef4a34a 619
454f18a9
BP
620DPRINT_ENTER(STORVSC);
621
622storDriver = (STORVSC_DRIVER_OBJECT*) device->Driver;
623storDriver->OnHostRescan(device);
624
625DPRINT_EXIT(STORVSC);
626}
627*********** */
bef4a34a 628
bd1de709 629static int
bef4a34a 630StorVscOnHostReset(
3d3b5518 631 struct hv_device *Device
bef4a34a
HJ
632 )
633{
634 int ret=0;
635
636 STORVSC_DEVICE *storDevice;
637 STORVSC_REQUEST_EXTENSION *request;
638 VSTOR_PACKET *vstorPacket;
639
640 DPRINT_ENTER(STORVSC);
641
642 DPRINT_INFO(STORVSC, "resetting host adapter...");
643
644 storDevice = GetStorDevice(Device);
645 if (!storDevice)
646 {
647 DPRINT_ERR(STORVSC, "unable to get stor device...device being destroyed?");
648 DPRINT_EXIT(STORVSC);
649 return -1;
650 }
651
652 request = &storDevice->ResetRequest;
653 vstorPacket = &request->VStorPacket;
654
bfc30aae 655 request->WaitEvent = osd_WaitEventCreate();
bef4a34a
HJ
656
657 vstorPacket->Operation = VStorOperationResetBus;
658 vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
659 vstorPacket->VmSrb.PathId = storDevice->PathId;
660
661 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
662 vstorPacket,
663 sizeof(VSTOR_PACKET),
c4b0bc94 664 (unsigned long)&storDevice->ResetRequest,
bef4a34a
HJ
665 VmbusPacketTypeDataInBand,
666 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
667 if (ret != 0)
668 {
669 DPRINT_ERR(STORVSC, "Unable to send reset packet %p ret %d", vstorPacket, ret);
670 goto Cleanup;
671 }
672
454f18a9 673 /* FIXME: Add a timeout */
bfc30aae 674 osd_WaitEventWait(request->WaitEvent);
bef4a34a 675
420beac4 676 kfree(request->WaitEvent);
bef4a34a
HJ
677 DPRINT_INFO(STORVSC, "host adapter reset completed");
678
454f18a9
BP
679 /*
680 * At this point, all outstanding requests in the adapter
681 * should have been flushed out and return to us
682 */
bef4a34a
HJ
683
684Cleanup:
685 PutStorDevice(Device);
686 DPRINT_EXIT(STORVSC);
687 return ret;
688}
689
690/*++
691
692Name:
693 StorVscOnIORequest()
694
695Description:
696 Callback to initiate an I/O request
697
698--*/
bd1de709 699static int
bef4a34a 700StorVscOnIORequest(
3d3b5518 701 struct hv_device *Device,
0b3f6834 702 struct hv_storvsc_request *Request
bef4a34a
HJ
703 )
704{
705 STORVSC_DEVICE *storDevice;
706 STORVSC_REQUEST_EXTENSION* requestExtension = (STORVSC_REQUEST_EXTENSION*) Request->Extension;
707 VSTOR_PACKET* vstorPacket =&requestExtension->VStorPacket;
708 int ret=0;
709
710 DPRINT_ENTER(STORVSC);
711
712 storDevice = GetStorDevice(Device);
713
714 DPRINT_DBG(STORVSC, "enter - Device %p, DeviceExt %p, Request %p, Extension %p",
715 Device, storDevice, Request, requestExtension);
716
717 DPRINT_DBG(STORVSC, "req %p len %d bus %d, target %d, lun %d cdblen %d",
718 Request, Request->DataBuffer.Length, Request->Bus, Request->TargetId, Request->LunId, Request->CdbLen);
719
720 if (!storDevice)
721 {
722 DPRINT_ERR(STORVSC, "unable to get stor device...device being destroyed?");
723 DPRINT_EXIT(STORVSC);
724 return -2;
725 }
726
04f50c4d 727 /* print_hex_dump_bytes("", DUMP_PREFIX_NONE, Request->Cdb, Request->CdbLen); */
bef4a34a
HJ
728
729 requestExtension->Request = Request;
730 requestExtension->Device = Device;
731
732 memset(vstorPacket, 0 , sizeof(VSTOR_PACKET));
733
734 vstorPacket->Flags |= REQUEST_COMPLETION_FLAG;
735
736 vstorPacket->VmSrb.Length = sizeof(VMSCSI_REQUEST);
737
738 vstorPacket->VmSrb.PortNumber = Request->Host;
739 vstorPacket->VmSrb.PathId = Request->Bus;
740 vstorPacket->VmSrb.TargetId = Request->TargetId;
741 vstorPacket->VmSrb.Lun = Request->LunId;
742
743 vstorPacket->VmSrb.SenseInfoLength = SENSE_BUFFER_SIZE;
744
454f18a9 745 /* Copy over the scsi command descriptor block */
bef4a34a
HJ
746 vstorPacket->VmSrb.CdbLength = Request->CdbLen;
747 memcpy(&vstorPacket->VmSrb.Cdb, Request->Cdb, Request->CdbLen);
748
749 vstorPacket->VmSrb.DataIn = Request->Type;
750 vstorPacket->VmSrb.DataTransferLength = Request->DataBuffer.Length;
751
752 vstorPacket->Operation = VStorOperationExecuteSRB;
753
754 DPRINT_DBG(STORVSC, "srb - len %d port %d, path %d, target %d, lun %d senselen %d cdblen %d",
755 vstorPacket->VmSrb.Length,
756 vstorPacket->VmSrb.PortNumber,
757 vstorPacket->VmSrb.PathId,
758 vstorPacket->VmSrb.TargetId,
759 vstorPacket->VmSrb.Lun,
760 vstorPacket->VmSrb.SenseInfoLength,
761 vstorPacket->VmSrb.CdbLength);
762
763 if (requestExtension->Request->DataBuffer.Length)
764 {
765 ret = Device->Driver->VmbusChannelInterface.SendPacketMultiPageBuffer(Device,
766 &requestExtension->Request->DataBuffer,
767 vstorPacket,
768 sizeof(VSTOR_PACKET),
c4b0bc94 769 (unsigned long)requestExtension);
bef4a34a
HJ
770 }
771 else
772 {
773 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
774 vstorPacket,
775 sizeof(VSTOR_PACKET),
c4b0bc94 776 (unsigned long)requestExtension,
bef4a34a
HJ
777 VmbusPacketTypeDataInBand,
778 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
779 }
780
781 if (ret != 0)
782 {
783 DPRINT_DBG(STORVSC, "Unable to send packet %p ret %d", vstorPacket, ret);
784 }
785
f4888417 786 atomic_inc(&storDevice->NumOutstandingRequests);
bef4a34a
HJ
787
788 PutStorDevice(Device);
789
790 DPRINT_EXIT(STORVSC);
791 return ret;
792}
793
794/*++
795
796Name:
797 StorVscOnCleanup()
798
799Description:
800 Perform any cleanup when the driver is removed
801
802--*/
bd1de709 803static void
bef4a34a 804StorVscOnCleanup(
775ef25e 805 struct hv_driver *Driver
bef4a34a
HJ
806 )
807{
808 DPRINT_ENTER(STORVSC);
809 DPRINT_EXIT(STORVSC);
810}
811
812
813static void
814StorVscOnIOCompletion(
3d3b5518 815 struct hv_device *Device,
bef4a34a
HJ
816 VSTOR_PACKET *VStorPacket,
817 STORVSC_REQUEST_EXTENSION *RequestExt
818 )
819{
0b3f6834 820 struct hv_storvsc_request *request;
bef4a34a
HJ
821 STORVSC_DEVICE *storDevice;
822
823 DPRINT_ENTER(STORVSC);
824
825 storDevice = MustGetStorDevice(Device);
826 if (!storDevice)
827 {
828 DPRINT_ERR(STORVSC, "unable to get stor device...device being destroyed?");
829 DPRINT_EXIT(STORVSC);
830 return;
831 }
832
78cd2003 833 DPRINT_DBG(STORVSC, "IO_COMPLETE_OPERATION - request extension %p completed bytes xfer %u",
bef4a34a
HJ
834 RequestExt, VStorPacket->VmSrb.DataTransferLength);
835
836 ASSERT(RequestExt != NULL);
837 ASSERT(RequestExt->Request != NULL);
838
839 request = RequestExt->Request;
840
841 ASSERT(request->OnIOCompletion != NULL);
842
454f18a9 843 /* Copy over the status...etc */
bef4a34a
HJ
844 request->Status = VStorPacket->VmSrb.ScsiStatus;
845
846 if (request->Status != 0 || VStorPacket->VmSrb.SrbStatus != 1)
847 {
848 DPRINT_WARN(STORVSC, "cmd 0x%x scsi status 0x%x srb status 0x%x\n",
849 request->Cdb[0],
850 VStorPacket->VmSrb.ScsiStatus,
851 VStorPacket->VmSrb.SrbStatus);
852 }
853
454f18a9 854 if ((request->Status & 0xFF) == 0x02) /* CHECK_CONDITION */
bef4a34a 855 {
454f18a9 856 if (VStorPacket->VmSrb.SrbStatus & 0x80) /* autosense data available */
bef4a34a
HJ
857 {
858 DPRINT_WARN(STORVSC, "storvsc pkt %p autosense data valid - len %d\n",
859 RequestExt, VStorPacket->VmSrb.SenseInfoLength);
860
861 ASSERT(VStorPacket->VmSrb.SenseInfoLength <= request->SenseBufferSize);
862 memcpy(request->SenseBuffer,
863 VStorPacket->VmSrb.SenseData,
864 VStorPacket->VmSrb.SenseInfoLength);
865
866 request->SenseBufferSize = VStorPacket->VmSrb.SenseInfoLength;
867 }
868 }
869
454f18a9 870 /* TODO: */
bef4a34a
HJ
871 request->BytesXfer = VStorPacket->VmSrb.DataTransferLength;
872
873 request->OnIOCompletion(request);
874
f4888417 875 atomic_dec(&storDevice->NumOutstandingRequests);
bef4a34a
HJ
876
877 PutStorDevice(Device);
878
879 DPRINT_EXIT(STORVSC);
880}
881
882
883static void
884StorVscOnReceive(
3d3b5518 885 struct hv_device *Device,
bef4a34a
HJ
886 VSTOR_PACKET *VStorPacket,
887 STORVSC_REQUEST_EXTENSION *RequestExt
888 )
889{
890 switch(VStorPacket->Operation)
891 {
892 case VStorOperationCompleteIo:
893
894 DPRINT_DBG(STORVSC, "IO_COMPLETE_OPERATION");
895 StorVscOnIOCompletion(Device, VStorPacket, RequestExt);
896 break;
897
454f18a9 898 /* case ENUMERATE_DEVICE_OPERATION: */
bef4a34a 899
454f18a9 900 /* DPRINT_INFO(STORVSC, "ENUMERATE_DEVICE_OPERATION"); */
bef4a34a 901
454f18a9
BP
902 /* StorVscOnTargetRescan(Device); */
903 /* break; */
bef4a34a 904
454f18a9 905 case VStorOperationRemoveDevice:
bef4a34a
HJ
906
907 DPRINT_INFO(STORVSC, "REMOVE_DEVICE_OPERATION");
454f18a9 908 /* TODO: */
bef4a34a
HJ
909 break;
910
911 default:
912 DPRINT_INFO(STORVSC, "Unknown operation received - %d", VStorPacket->Operation);
913 break;
914 }
915}
916
bd1de709 917static void
bef4a34a 918StorVscOnChannelCallback(
8282c400 919 void * Context
bef4a34a
HJ
920 )
921{
922 int ret=0;
3d3b5518 923 struct hv_device *device = (struct hv_device*)Context;
bef4a34a 924 STORVSC_DEVICE *storDevice;
4d643114 925 u32 bytesRecvd;
59471438
GKH
926 u64 requestId;
927 unsigned char packet[ALIGN_UP(sizeof(VSTOR_PACKET),8)];
bef4a34a
HJ
928 STORVSC_REQUEST_EXTENSION *request;
929
930 DPRINT_ENTER(STORVSC);
931
932 ASSERT(device);
933
934 storDevice = MustGetStorDevice(device);
935 if (!storDevice)
936 {
937 DPRINT_ERR(STORVSC, "unable to get stor device...device being destroyed?");
938 DPRINT_EXIT(STORVSC);
939 return;
940 }
941
942 do
943 {
944 ret = device->Driver->VmbusChannelInterface.RecvPacket(device,
945 packet,
946 ALIGN_UP(sizeof(VSTOR_PACKET),8),
947 &bytesRecvd,
948 &requestId);
949 if (ret == 0 && bytesRecvd > 0)
950 {
951 DPRINT_DBG(STORVSC, "receive %d bytes - tid %llx", bytesRecvd, requestId);
952
454f18a9 953 /* ASSERT(bytesRecvd == sizeof(VSTOR_PACKET)); */
bef4a34a 954
c4b0bc94 955 request = (STORVSC_REQUEST_EXTENSION*)(unsigned long)requestId;
bef4a34a
HJ
956 ASSERT(request);
957
454f18a9 958 /* if (vstorPacket.Flags & SYNTHETIC_FLAG) */
bef4a34a
HJ
959 if ((request == &storDevice->InitRequest) || (request == &storDevice->ResetRequest))
960 {
454f18a9 961 /* DPRINT_INFO(STORVSC, "reset completion - operation %u status %u", vstorPacket.Operation, vstorPacket.Status); */
bef4a34a
HJ
962
963 memcpy(&request->VStorPacket, packet, sizeof(VSTOR_PACKET));
964
bfc30aae 965 osd_WaitEventSet(request->WaitEvent);
bef4a34a
HJ
966 }
967 else
968 {
969 StorVscOnReceive(device, (VSTOR_PACKET*)packet, request);
970 }
971 }
972 else
973 {
454f18a9 974 /* DPRINT_DBG(STORVSC, "nothing else to read..."); */
bef4a34a
HJ
975 break;
976 }
977 } while (1);
978
979 PutStorDevice(device);
980
981 DPRINT_EXIT(STORVSC);
982 return;
983}
This page took 0.075616 seconds and 5 git commands to generate.