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