Deleted Added
full compact
hv_storvsc_drv_freebsd.c (307302) hv_storvsc_drv_freebsd.c (307307)
1/*-
2 * Copyright (c) 2009-2012,2016 Microsoft Corp.
3 * Copyright (c) 2012 NetApp Inc.
4 * Copyright (c) 2012 Citrix Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 19 unchanged lines hidden (view full) ---

28
29/**
30 * StorVSC driver for Hyper-V. This driver presents a SCSI HBA interface
31 * to the Comman Access Method (CAM) layer. CAM control blocks (CCBs) are
32 * converted into VSCSI protocol messages which are delivered to the parent
33 * partition StorVSP driver over the Hyper-V VMBUS.
34 */
35#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2009-2012,2016 Microsoft Corp.
3 * Copyright (c) 2012 NetApp Inc.
4 * Copyright (c) 2012 Citrix Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 19 unchanged lines hidden (view full) ---

28
29/**
30 * StorVSC driver for Hyper-V. This driver presents a SCSI HBA interface
31 * to the Comman Access Method (CAM) layer. CAM control blocks (CCBs) are
32 * converted into VSCSI protocol messages which are delivered to the parent
33 * partition StorVSP driver over the Hyper-V VMBUS.
34 */
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD: stable/11/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c 307302 2016-10-14 08:02:37Z sephe $");
36__FBSDID("$FreeBSD: stable/11/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c 307307 2016-10-14 08:45:53Z sephe $");
37
38#include <sys/param.h>
39#include <sys/proc.h>
40#include <sys/condvar.h>
41#include <sys/time.h>
42#include <sys/systm.h>
43#include <sys/sockio.h>
44#include <sys/mbuf.h>

--- 75 unchanged lines hidden (view full) ---

120 struct callout callout;
121 struct sema synch_sema; /*Synchronize the request/response if needed */
122 struct sglist *bounce_sgl;
123 unsigned int bounce_sgl_count;
124 uint64_t not_aligned_seg_bits;
125};
126
127struct storvsc_softc {
37
38#include <sys/param.h>
39#include <sys/proc.h>
40#include <sys/condvar.h>
41#include <sys/time.h>
42#include <sys/systm.h>
43#include <sys/sockio.h>
44#include <sys/mbuf.h>

--- 75 unchanged lines hidden (view full) ---

120 struct callout callout;
121 struct sema synch_sema; /*Synchronize the request/response if needed */
122 struct sglist *bounce_sgl;
123 unsigned int bounce_sgl_count;
124 uint64_t not_aligned_seg_bits;
125};
126
127struct storvsc_softc {
128 struct hv_device *hs_dev;
128 struct hv_vmbus_channel *hs_chan;
129 LIST_HEAD(, hv_storvsc_request) hs_free_list;
130 struct mtx hs_lock;
131 struct storvsc_driver_props *hs_drv_props;
132 int hs_unit;
133 uint32_t hs_frozen;
134 struct cam_sim *hs_sim;
135 struct cam_path *hs_path;
136 uint32_t hs_num_out_reqs;
137 boolean_t hs_destroy;
138 boolean_t hs_drain_notify;
139 struct sema hs_drain_sema;
140 struct hv_storvsc_request hs_init_req;
141 struct hv_storvsc_request hs_reset_req;
129 LIST_HEAD(, hv_storvsc_request) hs_free_list;
130 struct mtx hs_lock;
131 struct storvsc_driver_props *hs_drv_props;
132 int hs_unit;
133 uint32_t hs_frozen;
134 struct cam_sim *hs_sim;
135 struct cam_path *hs_path;
136 uint32_t hs_num_out_reqs;
137 boolean_t hs_destroy;
138 boolean_t hs_drain_notify;
139 struct sema hs_drain_sema;
140 struct hv_storvsc_request hs_init_req;
141 struct hv_storvsc_request hs_reset_req;
142 device_t hs_dev;
142};
143
144
145/**
146 * HyperV storvsc timeout testing cases:
147 * a. IO returned after first timeout;
148 * b. IO returned after second timeout and queue freeze;
149 * c. IO returned while timer handler is running

--- 109 unchanged lines hidden (view full) ---

259static int storvsc_attach(device_t dev);
260static int storvsc_detach(device_t dev);
261static void storvsc_poll(struct cam_sim * sim);
262static void storvsc_action(struct cam_sim * sim, union ccb * ccb);
263static int create_storvsc_request(union ccb *ccb, struct hv_storvsc_request *reqp);
264static void storvsc_free_request(struct storvsc_softc *sc, struct hv_storvsc_request *reqp);
265static enum hv_storage_type storvsc_get_storage_type(device_t dev);
266static void hv_storvsc_rescan_target(struct storvsc_softc *sc);
143};
144
145
146/**
147 * HyperV storvsc timeout testing cases:
148 * a. IO returned after first timeout;
149 * b. IO returned after second timeout and queue freeze;
150 * c. IO returned while timer handler is running

--- 109 unchanged lines hidden (view full) ---

260static int storvsc_attach(device_t dev);
261static int storvsc_detach(device_t dev);
262static void storvsc_poll(struct cam_sim * sim);
263static void storvsc_action(struct cam_sim * sim, union ccb * ccb);
264static int create_storvsc_request(union ccb *ccb, struct hv_storvsc_request *reqp);
265static void storvsc_free_request(struct storvsc_softc *sc, struct hv_storvsc_request *reqp);
266static enum hv_storage_type storvsc_get_storage_type(device_t dev);
267static void hv_storvsc_rescan_target(struct storvsc_softc *sc);
267static void hv_storvsc_on_channel_callback(void *context);
268static void hv_storvsc_on_channel_callback(void *xchan);
268static void hv_storvsc_on_iocompletion( struct storvsc_softc *sc,
269 struct vstor_packet *vstor_packet,
270 struct hv_storvsc_request *request);
269static void hv_storvsc_on_iocompletion( struct storvsc_softc *sc,
270 struct vstor_packet *vstor_packet,
271 struct hv_storvsc_request *request);
271static int hv_storvsc_connect_vsp(struct hv_device *device);
272static int hv_storvsc_connect_vsp(struct storvsc_softc *);
272static void storvsc_io_done(struct hv_storvsc_request *reqp);
273static void storvsc_copy_sgl_to_bounce_buf(struct sglist *bounce_sgl,
274 bus_dma_segment_t *orig_sgl,
275 unsigned int orig_sgl_count,
276 uint64_t seg_bits);
277void storvsc_copy_from_bounce_buf_to_sgl(bus_dma_segment_t *dest_sgl,
278 unsigned int dest_sgl_count,
279 struct sglist* src_sgl,

--- 12 unchanged lines hidden (view full) ---

292 "storvsc", storvsc_methods, sizeof(struct storvsc_softc),
293};
294
295static devclass_t storvsc_devclass;
296DRIVER_MODULE(storvsc, vmbus, storvsc_driver, storvsc_devclass, 0, 0);
297MODULE_VERSION(storvsc, 1);
298MODULE_DEPEND(storvsc, vmbus, 1, 1, 1);
299
273static void storvsc_io_done(struct hv_storvsc_request *reqp);
274static void storvsc_copy_sgl_to_bounce_buf(struct sglist *bounce_sgl,
275 bus_dma_segment_t *orig_sgl,
276 unsigned int orig_sgl_count,
277 uint64_t seg_bits);
278void storvsc_copy_from_bounce_buf_to_sgl(bus_dma_segment_t *dest_sgl,
279 unsigned int dest_sgl_count,
280 struct sglist* src_sgl,

--- 12 unchanged lines hidden (view full) ---

293 "storvsc", storvsc_methods, sizeof(struct storvsc_softc),
294};
295
296static devclass_t storvsc_devclass;
297DRIVER_MODULE(storvsc, vmbus, storvsc_driver, storvsc_devclass, 0, 0);
298MODULE_VERSION(storvsc, 1);
299MODULE_DEPEND(storvsc, vmbus, 1, 1, 1);
300
300
301/**
302 * The host is capable of sending messages to us that are
303 * completely unsolicited. So, we need to address the race
304 * condition where we may be in the process of unloading the
305 * driver when the host may send us an unsolicited message.
306 * We address this issue by implementing a sequentially
307 * consistent protocol:
308 *
309 * 1. Channel callback is invoked while holding the channel lock
310 * and an unloading driver will reset the channel callback under
311 * the protection of this channel lock.
312 *
313 * 2. To ensure bounded wait time for unloading a driver, we don't
314 * permit outgoing traffic once the device is marked as being
315 * destroyed.
316 *
317 * 3. Once the device is marked as being destroyed, we only
318 * permit incoming traffic to properly account for
319 * packets already sent out.
320 */
321static inline struct storvsc_softc *
322get_stor_device(struct hv_device *device,
323 boolean_t outbound)
324{
325 struct storvsc_softc *sc;
326
327 sc = device_get_softc(device->device);
328
329 if (outbound) {
330 /*
331 * Here we permit outgoing I/O only
332 * if the device is not being destroyed.
333 */
334
335 if (sc->hs_destroy) {
336 sc = NULL;
337 }
338 } else {
339 /*
340 * inbound case; if being destroyed
341 * only permit to account for
342 * messages already sent out.
343 */
344 if (sc->hs_destroy && (sc->hs_num_out_reqs == 0)) {
345 sc = NULL;
346 }
347 }
348 return sc;
349}
350
351static void
301static void
352storvsc_subchan_attach(struct hv_vmbus_channel *new_channel)
302storvsc_subchan_attach(struct storvsc_softc *sc,
303 struct hv_vmbus_channel *new_channel)
353{
304{
354 struct hv_device *device;
355 struct storvsc_softc *sc;
356 struct vmstor_chan_props props;
357 int ret = 0;
358
305 struct vmstor_chan_props props;
306 int ret = 0;
307
359 device = new_channel->device;
360 sc = get_stor_device(device, TRUE);
361 if (sc == NULL)
362 return;
363
364 memset(&props, 0, sizeof(props));
365
308 memset(&props, 0, sizeof(props));
309
310 new_channel->hv_chan_priv1 = sc;
366 vmbus_channel_cpu_rr(new_channel);
367 ret = hv_vmbus_channel_open(new_channel,
368 sc->hs_drv_props->drv_ringbuffer_size,
369 sc->hs_drv_props->drv_ringbuffer_size,
370 (void *)&props,
371 sizeof(struct vmstor_chan_props),
372 hv_storvsc_on_channel_callback,
373 new_channel);
311 vmbus_channel_cpu_rr(new_channel);
312 ret = hv_vmbus_channel_open(new_channel,
313 sc->hs_drv_props->drv_ringbuffer_size,
314 sc->hs_drv_props->drv_ringbuffer_size,
315 (void *)&props,
316 sizeof(struct vmstor_chan_props),
317 hv_storvsc_on_channel_callback,
318 new_channel);
374
375 return;
376}
377
378/**
379 * @brief Send multi-channel creation request to host
380 *
381 * @param device a Hyper-V device pointer
382 * @param max_chans the max channels supported by vmbus
383 */
384static void
319}
320
321/**
322 * @brief Send multi-channel creation request to host
323 *
324 * @param device a Hyper-V device pointer
325 * @param max_chans the max channels supported by vmbus
326 */
327static void
385storvsc_send_multichannel_request(struct hv_device *dev, int max_chans)
328storvsc_send_multichannel_request(struct storvsc_softc *sc, int max_chans)
386{
387 struct hv_vmbus_channel **subchan;
329{
330 struct hv_vmbus_channel **subchan;
388 struct storvsc_softc *sc;
389 struct hv_storvsc_request *request;
390 struct vstor_packet *vstor_packet;
391 int request_channels_cnt = 0;
392 int ret, i;
393
394 /* get multichannels count that need to create */
395 request_channels_cnt = MIN(max_chans, mp_ncpus);
396
331 struct hv_storvsc_request *request;
332 struct vstor_packet *vstor_packet;
333 int request_channels_cnt = 0;
334 int ret, i;
335
336 /* get multichannels count that need to create */
337 request_channels_cnt = MIN(max_chans, mp_ncpus);
338
397 sc = get_stor_device(dev, TRUE);
398 if (sc == NULL) {
399 printf("Storvsc_error: get sc failed while send mutilchannel "
400 "request\n");
401 return;
402 }
403
404 request = &sc->hs_init_req;
405
406 /* request the host to create multi-channel */
407 memset(request, 0, sizeof(struct hv_storvsc_request));
408
409 sema_init(&request->synch_sema, 0, ("stor_synch_sema"));
410
411 vstor_packet = &request->vstor_packet;
412
413 vstor_packet->operation = VSTOR_OPERATION_CREATE_MULTI_CHANNELS;
414 vstor_packet->flags = REQUEST_COMPLETION_FLAG;
415 vstor_packet->u.multi_channels_cnt = request_channels_cnt;
416
417 ret = hv_vmbus_channel_send_packet(
339 request = &sc->hs_init_req;
340
341 /* request the host to create multi-channel */
342 memset(request, 0, sizeof(struct hv_storvsc_request));
343
344 sema_init(&request->synch_sema, 0, ("stor_synch_sema"));
345
346 vstor_packet = &request->vstor_packet;
347
348 vstor_packet->operation = VSTOR_OPERATION_CREATE_MULTI_CHANNELS;
349 vstor_packet->flags = REQUEST_COMPLETION_FLAG;
350 vstor_packet->u.multi_channels_cnt = request_channels_cnt;
351
352 ret = hv_vmbus_channel_send_packet(
418 dev->channel,
353 sc->hs_chan,
419 vstor_packet,
420 VSTOR_PKT_SIZE,
421 (uint64_t)(uintptr_t)request,
422 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
423 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
424
425 /* wait for 5 seconds */
426 ret = sema_timedwait(&request->synch_sema, 5 * hz);

--- 7 unchanged lines hidden (view full) ---

434 vstor_packet->status != 0) {
435 printf("Storvsc_error: create multi-channel invalid operation "
436 "(%d) or statue (%u)\n",
437 vstor_packet->operation, vstor_packet->status);
438 return;
439 }
440
441 /* Wait for sub-channels setup to complete. */
354 vstor_packet,
355 VSTOR_PKT_SIZE,
356 (uint64_t)(uintptr_t)request,
357 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
358 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
359
360 /* wait for 5 seconds */
361 ret = sema_timedwait(&request->synch_sema, 5 * hz);

--- 7 unchanged lines hidden (view full) ---

369 vstor_packet->status != 0) {
370 printf("Storvsc_error: create multi-channel invalid operation "
371 "(%d) or statue (%u)\n",
372 vstor_packet->operation, vstor_packet->status);
373 return;
374 }
375
376 /* Wait for sub-channels setup to complete. */
442 subchan = vmbus_get_subchan(dev->channel, request_channels_cnt);
377 subchan = vmbus_get_subchan(sc->hs_chan, request_channels_cnt);
443
444 /* Attach the sub-channels. */
445 for (i = 0; i < request_channels_cnt; ++i)
378
379 /* Attach the sub-channels. */
380 for (i = 0; i < request_channels_cnt; ++i)
446 storvsc_subchan_attach(subchan[i]);
381 storvsc_subchan_attach(sc, subchan[i]);
447
448 /* Release the sub-channels. */
449 vmbus_rel_subchan(subchan, request_channels_cnt);
450
451 if (bootverbose)
452 printf("Storvsc create multi-channel success!\n");
453}
454
455/**
456 * @brief initialize channel connection to parent partition
457 *
458 * @param dev a Hyper-V device pointer
459 * @returns 0 on success, non-zero error on failure
460 */
461static int
382
383 /* Release the sub-channels. */
384 vmbus_rel_subchan(subchan, request_channels_cnt);
385
386 if (bootverbose)
387 printf("Storvsc create multi-channel success!\n");
388}
389
390/**
391 * @brief initialize channel connection to parent partition
392 *
393 * @param dev a Hyper-V device pointer
394 * @returns 0 on success, non-zero error on failure
395 */
396static int
462hv_storvsc_channel_init(struct hv_device *dev)
397hv_storvsc_channel_init(struct storvsc_softc *sc)
463{
464 int ret = 0, i;
465 struct hv_storvsc_request *request;
466 struct vstor_packet *vstor_packet;
398{
399 int ret = 0, i;
400 struct hv_storvsc_request *request;
401 struct vstor_packet *vstor_packet;
467 struct storvsc_softc *sc;
468 uint16_t max_chans = 0;
469 boolean_t support_multichannel = FALSE;
470 uint32_t version;
471
472 max_chans = 0;
473 support_multichannel = FALSE;
474
402 uint16_t max_chans = 0;
403 boolean_t support_multichannel = FALSE;
404 uint32_t version;
405
406 max_chans = 0;
407 support_multichannel = FALSE;
408
475 sc = get_stor_device(dev, TRUE);
476 if (sc == NULL)
477 return (ENODEV);
478
479 request = &sc->hs_init_req;
480 memset(request, 0, sizeof(struct hv_storvsc_request));
481 vstor_packet = &request->vstor_packet;
482 request->softc = sc;
483
484 /**
485 * Initiate the vsc/vsp initialization protocol on the open channel
486 */
487 sema_init(&request->synch_sema, 0, ("stor_synch_sema"));
488
489 vstor_packet->operation = VSTOR_OPERATION_BEGININITIALIZATION;
490 vstor_packet->flags = REQUEST_COMPLETION_FLAG;
491
492
493 ret = hv_vmbus_channel_send_packet(
409 request = &sc->hs_init_req;
410 memset(request, 0, sizeof(struct hv_storvsc_request));
411 vstor_packet = &request->vstor_packet;
412 request->softc = sc;
413
414 /**
415 * Initiate the vsc/vsp initialization protocol on the open channel
416 */
417 sema_init(&request->synch_sema, 0, ("stor_synch_sema"));
418
419 vstor_packet->operation = VSTOR_OPERATION_BEGININITIALIZATION;
420 vstor_packet->flags = REQUEST_COMPLETION_FLAG;
421
422
423 ret = hv_vmbus_channel_send_packet(
494 dev->channel,
424 sc->hs_chan,
495 vstor_packet,
496 VSTOR_PKT_SIZE,
497 (uint64_t)(uintptr_t)request,
498 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
499 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
500
501 if (ret != 0)
502 goto cleanup;

--- 17 unchanged lines hidden (view full) ---

520
521 vstor_packet->u.version.major_minor =
522 vmstor_proto_list[i].proto_version;
523
524 /* revision is only significant for Windows guests */
525 vstor_packet->u.version.revision = 0;
526
527 ret = hv_vmbus_channel_send_packet(
425 vstor_packet,
426 VSTOR_PKT_SIZE,
427 (uint64_t)(uintptr_t)request,
428 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
429 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
430
431 if (ret != 0)
432 goto cleanup;

--- 17 unchanged lines hidden (view full) ---

450
451 vstor_packet->u.version.major_minor =
452 vmstor_proto_list[i].proto_version;
453
454 /* revision is only significant for Windows guests */
455 vstor_packet->u.version.revision = 0;
456
457 ret = hv_vmbus_channel_send_packet(
528 dev->channel,
458 sc->hs_chan,
529 vstor_packet,
530 VSTOR_PKT_SIZE,
531 (uint64_t)(uintptr_t)request,
532 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
533 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
534
535 if (ret != 0)
536 goto cleanup;

--- 26 unchanged lines hidden (view full) ---

563 /**
564 * Query channel properties
565 */
566 memset(vstor_packet, 0, sizeof(struct vstor_packet));
567 vstor_packet->operation = VSTOR_OPERATION_QUERYPROPERTIES;
568 vstor_packet->flags = REQUEST_COMPLETION_FLAG;
569
570 ret = hv_vmbus_channel_send_packet(
459 vstor_packet,
460 VSTOR_PKT_SIZE,
461 (uint64_t)(uintptr_t)request,
462 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
463 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
464
465 if (ret != 0)
466 goto cleanup;

--- 26 unchanged lines hidden (view full) ---

493 /**
494 * Query channel properties
495 */
496 memset(vstor_packet, 0, sizeof(struct vstor_packet));
497 vstor_packet->operation = VSTOR_OPERATION_QUERYPROPERTIES;
498 vstor_packet->flags = REQUEST_COMPLETION_FLAG;
499
500 ret = hv_vmbus_channel_send_packet(
571 dev->channel,
501 sc->hs_chan,
572 vstor_packet,
573 VSTOR_PKT_SIZE,
574 (uint64_t)(uintptr_t)request,
575 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
576 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
577
578 if ( ret != 0)
579 goto cleanup;

--- 7 unchanged lines hidden (view full) ---

587 /* TODO: Check returned version */
588 if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO ||
589 vstor_packet->status != 0) {
590 goto cleanup;
591 }
592
593 /* multi-channels feature is supported by WIN8 and above version */
594 max_chans = vstor_packet->u.chan_props.max_channel_cnt;
502 vstor_packet,
503 VSTOR_PKT_SIZE,
504 (uint64_t)(uintptr_t)request,
505 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
506 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
507
508 if ( ret != 0)
509 goto cleanup;

--- 7 unchanged lines hidden (view full) ---

517 /* TODO: Check returned version */
518 if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO ||
519 vstor_packet->status != 0) {
520 goto cleanup;
521 }
522
523 /* multi-channels feature is supported by WIN8 and above version */
524 max_chans = vstor_packet->u.chan_props.max_channel_cnt;
595 version = VMBUS_GET_VERSION(device_get_parent(dev->device),
596 dev->device);
525 version = VMBUS_GET_VERSION(device_get_parent(sc->hs_dev), sc->hs_dev);
597 if (version != VMBUS_VERSION_WIN7 && version != VMBUS_VERSION_WS2008 &&
598 (vstor_packet->u.chan_props.flags &
599 HV_STORAGE_SUPPORTS_MULTI_CHANNEL)) {
600 support_multichannel = TRUE;
601 }
602
603 memset(vstor_packet, 0, sizeof(struct vstor_packet));
604 vstor_packet->operation = VSTOR_OPERATION_ENDINITIALIZATION;
605 vstor_packet->flags = REQUEST_COMPLETION_FLAG;
606
607 ret = hv_vmbus_channel_send_packet(
526 if (version != VMBUS_VERSION_WIN7 && version != VMBUS_VERSION_WS2008 &&
527 (vstor_packet->u.chan_props.flags &
528 HV_STORAGE_SUPPORTS_MULTI_CHANNEL)) {
529 support_multichannel = TRUE;
530 }
531
532 memset(vstor_packet, 0, sizeof(struct vstor_packet));
533 vstor_packet->operation = VSTOR_OPERATION_ENDINITIALIZATION;
534 vstor_packet->flags = REQUEST_COMPLETION_FLAG;
535
536 ret = hv_vmbus_channel_send_packet(
608 dev->channel,
537 sc->hs_chan,
609 vstor_packet,
610 VSTOR_PKT_SIZE,
611 (uint64_t)(uintptr_t)request,
612 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
613 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
614
615 if (ret != 0) {
616 goto cleanup;

--- 9 unchanged lines hidden (view full) ---

626 vstor_packet->status != 0)
627 goto cleanup;
628
629 /*
630 * If multi-channel is supported, send multichannel create
631 * request to host.
632 */
633 if (support_multichannel)
538 vstor_packet,
539 VSTOR_PKT_SIZE,
540 (uint64_t)(uintptr_t)request,
541 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
542 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
543
544 if (ret != 0) {
545 goto cleanup;

--- 9 unchanged lines hidden (view full) ---

555 vstor_packet->status != 0)
556 goto cleanup;
557
558 /*
559 * If multi-channel is supported, send multichannel create
560 * request to host.
561 */
562 if (support_multichannel)
634 storvsc_send_multichannel_request(dev, max_chans);
563 storvsc_send_multichannel_request(sc, max_chans);
635
636cleanup:
637 sema_destroy(&request->synch_sema);
638 return (ret);
639}
640
641/**
642 * @brief Open channel connection to paraent partition StorVSP driver
643 *
644 * Open and initialize channel connection to parent partition StorVSP driver.
645 *
646 * @param pointer to a Hyper-V device
647 * @returns 0 on success, non-zero error on failure
648 */
649static int
564
565cleanup:
566 sema_destroy(&request->synch_sema);
567 return (ret);
568}
569
570/**
571 * @brief Open channel connection to paraent partition StorVSP driver
572 *
573 * Open and initialize channel connection to parent partition StorVSP driver.
574 *
575 * @param pointer to a Hyper-V device
576 * @returns 0 on success, non-zero error on failure
577 */
578static int
650hv_storvsc_connect_vsp(struct hv_device *dev)
579hv_storvsc_connect_vsp(struct storvsc_softc *sc)
651{
652 int ret = 0;
653 struct vmstor_chan_props props;
580{
581 int ret = 0;
582 struct vmstor_chan_props props;
654 struct storvsc_softc *sc;
655
583
656 sc = device_get_softc(dev->device);
657
658 memset(&props, 0, sizeof(struct vmstor_chan_props));
659
660 /*
661 * Open the channel
662 */
584 memset(&props, 0, sizeof(struct vmstor_chan_props));
585
586 /*
587 * Open the channel
588 */
663 vmbus_channel_cpu_rr(dev->channel);
589 KASSERT(sc->hs_chan->hv_chan_priv1 == sc, ("invalid chan priv1"));
590 vmbus_channel_cpu_rr(sc->hs_chan);
664 ret = hv_vmbus_channel_open(
591 ret = hv_vmbus_channel_open(
665 dev->channel,
592 sc->hs_chan,
666 sc->hs_drv_props->drv_ringbuffer_size,
667 sc->hs_drv_props->drv_ringbuffer_size,
668 (void *)&props,
669 sizeof(struct vmstor_chan_props),
670 hv_storvsc_on_channel_callback,
593 sc->hs_drv_props->drv_ringbuffer_size,
594 sc->hs_drv_props->drv_ringbuffer_size,
595 (void *)&props,
596 sizeof(struct vmstor_chan_props),
597 hv_storvsc_on_channel_callback,
671 dev->channel);
598 sc->hs_chan);
672
673 if (ret != 0) {
674 return ret;
675 }
676
599
600 if (ret != 0) {
601 return ret;
602 }
603
677 ret = hv_storvsc_channel_init(dev);
604 ret = hv_storvsc_channel_init(sc);
678
679 return (ret);
680}
681
682#if HVS_HOST_RESET
683static int
605
606 return (ret);
607}
608
609#if HVS_HOST_RESET
610static int
684hv_storvsc_host_reset(struct hv_device *dev)
611hv_storvsc_host_reset(struct storvsc_softc *sc)
685{
686 int ret = 0;
612{
613 int ret = 0;
687 struct storvsc_softc *sc;
688
689 struct hv_storvsc_request *request;
690 struct vstor_packet *vstor_packet;
691
614
615 struct hv_storvsc_request *request;
616 struct vstor_packet *vstor_packet;
617
692 sc = get_stor_device(dev, TRUE);
693 if (sc == NULL) {
694 return ENODEV;
695 }
696
697 request = &sc->hs_reset_req;
698 request->softc = sc;
699 vstor_packet = &request->vstor_packet;
700
701 sema_init(&request->synch_sema, 0, "stor synch sema");
702
703 vstor_packet->operation = VSTOR_OPERATION_RESETBUS;
704 vstor_packet->flags = REQUEST_COMPLETION_FLAG;

--- 30 unchanged lines hidden (view full) ---

735/**
736 * @brief Function to initiate an I/O request
737 *
738 * @param device Hyper-V device pointer
739 * @param request pointer to a request structure
740 * @returns 0 on success, non-zero error on failure
741 */
742static int
618 request = &sc->hs_reset_req;
619 request->softc = sc;
620 vstor_packet = &request->vstor_packet;
621
622 sema_init(&request->synch_sema, 0, "stor synch sema");
623
624 vstor_packet->operation = VSTOR_OPERATION_RESETBUS;
625 vstor_packet->flags = REQUEST_COMPLETION_FLAG;

--- 30 unchanged lines hidden (view full) ---

656/**
657 * @brief Function to initiate an I/O request
658 *
659 * @param device Hyper-V device pointer
660 * @param request pointer to a request structure
661 * @returns 0 on success, non-zero error on failure
662 */
663static int
743hv_storvsc_io_request(struct hv_device *device,
664hv_storvsc_io_request(struct storvsc_softc *sc,
744 struct hv_storvsc_request *request)
745{
665 struct hv_storvsc_request *request)
666{
746 struct storvsc_softc *sc;
747 struct vstor_packet *vstor_packet = &request->vstor_packet;
748 struct hv_vmbus_channel* outgoing_channel = NULL;
749 int ret = 0;
750
667 struct vstor_packet *vstor_packet = &request->vstor_packet;
668 struct hv_vmbus_channel* outgoing_channel = NULL;
669 int ret = 0;
670
751 sc = get_stor_device(device, TRUE);
752
753 if (sc == NULL) {
754 return ENODEV;
755 }
756
757 vstor_packet->flags |= REQUEST_COMPLETION_FLAG;
758
759 vstor_packet->u.vm_srb.length =
760 sizeof(struct vmscsi_req) - vmscsi_size_delta;
761
762 vstor_packet->u.vm_srb.sense_info_len = sense_buffer_size;
763
764 vstor_packet->u.vm_srb.transfer_len = request->data_buf.length;
765
766 vstor_packet->operation = VSTOR_OPERATION_EXECUTESRB;
767
671 vstor_packet->flags |= REQUEST_COMPLETION_FLAG;
672
673 vstor_packet->u.vm_srb.length =
674 sizeof(struct vmscsi_req) - vmscsi_size_delta;
675
676 vstor_packet->u.vm_srb.sense_info_len = sense_buffer_size;
677
678 vstor_packet->u.vm_srb.transfer_len = request->data_buf.length;
679
680 vstor_packet->operation = VSTOR_OPERATION_EXECUTESRB;
681
768 outgoing_channel = vmbus_select_outgoing_channel(device->channel);
682 outgoing_channel = vmbus_select_outgoing_channel(sc->hs_chan);
769
770 mtx_unlock(&request->softc->hs_lock);
771 if (request->data_buf.length) {
772 ret = hv_vmbus_channel_send_packet_multipagebuffer(
773 outgoing_channel,
774 &request->data_buf,
775 vstor_packet,
776 VSTOR_PKT_SIZE,

--- 95 unchanged lines hidden (view full) ---

872 ccb->ccb_h.func_code = XPT_SCAN_BUS;
873 else
874 ccb->ccb_h.func_code = XPT_SCAN_TGT;
875
876 xpt_rescan(ccb);
877}
878
879static void
683
684 mtx_unlock(&request->softc->hs_lock);
685 if (request->data_buf.length) {
686 ret = hv_vmbus_channel_send_packet_multipagebuffer(
687 outgoing_channel,
688 &request->data_buf,
689 vstor_packet,
690 VSTOR_PKT_SIZE,

--- 95 unchanged lines hidden (view full) ---

786 ccb->ccb_h.func_code = XPT_SCAN_BUS;
787 else
788 ccb->ccb_h.func_code = XPT_SCAN_TGT;
789
790 xpt_rescan(ccb);
791}
792
793static void
880hv_storvsc_on_channel_callback(void *context)
794hv_storvsc_on_channel_callback(void *xchan)
881{
882 int ret = 0;
795{
796 int ret = 0;
883 hv_vmbus_channel *channel = (hv_vmbus_channel *)context;
884 struct hv_device *device = NULL;
885 struct storvsc_softc *sc;
797 hv_vmbus_channel *channel = xchan;
798 struct storvsc_softc *sc = channel->hv_chan_priv1;
886 uint32_t bytes_recvd;
887 uint64_t request_id;
888 uint8_t packet[roundup2(sizeof(struct vstor_packet), 8)];
889 struct hv_storvsc_request *request;
890 struct vstor_packet *vstor_packet;
891
799 uint32_t bytes_recvd;
800 uint64_t request_id;
801 uint8_t packet[roundup2(sizeof(struct vstor_packet), 8)];
802 struct hv_storvsc_request *request;
803 struct vstor_packet *vstor_packet;
804
892 device = channel->device;
893 KASSERT(device, ("device is NULL"));
894
895 sc = get_stor_device(device, FALSE);
896 if (sc == NULL) {
897 printf("Storvsc_error: get stor device failed.\n");
898 return;
899 }
900
901 ret = hv_vmbus_channel_recv_packet(
902 channel,
903 packet,
904 roundup2(VSTOR_PKT_SIZE, 8),
905 &bytes_recvd,
906 &request_id);
907
908 while ((ret == 0) && (bytes_recvd > 0)) {

--- 87 unchanged lines hidden (view full) ---

996 * be used for SCSI device peripherals.
997 *
998 * @param a device
999 * @returns 0 on success or an error on failure
1000 */
1001static int
1002storvsc_attach(device_t dev)
1003{
805 ret = hv_vmbus_channel_recv_packet(
806 channel,
807 packet,
808 roundup2(VSTOR_PKT_SIZE, 8),
809 &bytes_recvd,
810 &request_id);
811
812 while ((ret == 0) && (bytes_recvd > 0)) {

--- 87 unchanged lines hidden (view full) ---

900 * be used for SCSI device peripherals.
901 *
902 * @param a device
903 * @returns 0 on success or an error on failure
904 */
905static int
906storvsc_attach(device_t dev)
907{
1004 struct hv_device *hv_dev = vmbus_get_devctx(dev);
1005 enum hv_storage_type stor_type;
1006 struct storvsc_softc *sc;
1007 struct cam_devq *devq;
1008 int ret, i, j;
1009 struct hv_storvsc_request *reqp;
1010 struct root_hold_token *root_mount_token = NULL;
1011 struct hv_sgl_node *sgl_node = NULL;
1012 void *tmp_buff = NULL;
1013
1014 /*
1015 * We need to serialize storvsc attach calls.
1016 */
1017 root_mount_token = root_mount_hold("storvsc");
1018
1019 sc = device_get_softc(dev);
908 enum hv_storage_type stor_type;
909 struct storvsc_softc *sc;
910 struct cam_devq *devq;
911 int ret, i, j;
912 struct hv_storvsc_request *reqp;
913 struct root_hold_token *root_mount_token = NULL;
914 struct hv_sgl_node *sgl_node = NULL;
915 void *tmp_buff = NULL;
916
917 /*
918 * We need to serialize storvsc attach calls.
919 */
920 root_mount_token = root_mount_hold("storvsc");
921
922 sc = device_get_softc(dev);
923 sc->hs_chan = vmbus_get_channel(dev);
924 sc->hs_chan->hv_chan_priv1 = sc;
1020
1021 stor_type = storvsc_get_storage_type(dev);
1022
1023 if (stor_type == DRIVER_UNKNOWN) {
1024 ret = ENODEV;
1025 goto cleanup;
1026 }
1027
1028 /* fill in driver specific properties */
1029 sc->hs_drv_props = &g_drv_props_table[stor_type];
1030
1031 /* fill in device specific properties */
1032 sc->hs_unit = device_get_unit(dev);
925
926 stor_type = storvsc_get_storage_type(dev);
927
928 if (stor_type == DRIVER_UNKNOWN) {
929 ret = ENODEV;
930 goto cleanup;
931 }
932
933 /* fill in driver specific properties */
934 sc->hs_drv_props = &g_drv_props_table[stor_type];
935
936 /* fill in device specific properties */
937 sc->hs_unit = device_get_unit(dev);
1033 sc->hs_dev = hv_dev;
938 sc->hs_dev = dev;
1034
1035 LIST_INIT(&sc->hs_free_list);
1036 mtx_init(&sc->hs_lock, "hvslck", NULL, MTX_DEF);
1037
1038 for (i = 0; i < sc->hs_drv_props->drv_max_ios_per_target; ++i) {
1039 reqp = malloc(sizeof(struct hv_storvsc_request),
1040 M_DEVBUF, M_WAITOK|M_ZERO);
1041 reqp->softc = sc;

--- 32 unchanged lines hidden (view full) ---

1074 sgl_node, link);
1075 }
1076 }
1077
1078 sc->hs_destroy = FALSE;
1079 sc->hs_drain_notify = FALSE;
1080 sema_init(&sc->hs_drain_sema, 0, "Store Drain Sema");
1081
939
940 LIST_INIT(&sc->hs_free_list);
941 mtx_init(&sc->hs_lock, "hvslck", NULL, MTX_DEF);
942
943 for (i = 0; i < sc->hs_drv_props->drv_max_ios_per_target; ++i) {
944 reqp = malloc(sizeof(struct hv_storvsc_request),
945 M_DEVBUF, M_WAITOK|M_ZERO);
946 reqp->softc = sc;

--- 32 unchanged lines hidden (view full) ---

979 sgl_node, link);
980 }
981 }
982
983 sc->hs_destroy = FALSE;
984 sc->hs_drain_notify = FALSE;
985 sema_init(&sc->hs_drain_sema, 0, "Store Drain Sema");
986
1082 ret = hv_storvsc_connect_vsp(hv_dev);
987 ret = hv_storvsc_connect_vsp(sc);
1083 if (ret != 0) {
1084 goto cleanup;
1085 }
1086
1087 /*
1088 * Create the device queue.
1089 * Hyper-V maps each target to one SCSI HBA
1090 */

--- 81 unchanged lines hidden (view full) ---

1172 * @param dev a device
1173 * returns 0 on success
1174 */
1175static int
1176storvsc_detach(device_t dev)
1177{
1178 struct storvsc_softc *sc = device_get_softc(dev);
1179 struct hv_storvsc_request *reqp = NULL;
988 if (ret != 0) {
989 goto cleanup;
990 }
991
992 /*
993 * Create the device queue.
994 * Hyper-V maps each target to one SCSI HBA
995 */

--- 81 unchanged lines hidden (view full) ---

1077 * @param dev a device
1078 * returns 0 on success
1079 */
1080static int
1081storvsc_detach(device_t dev)
1082{
1083 struct storvsc_softc *sc = device_get_softc(dev);
1084 struct hv_storvsc_request *reqp = NULL;
1180 struct hv_device *hv_device = vmbus_get_devctx(dev);
1181 struct hv_sgl_node *sgl_node = NULL;
1182 int j = 0;
1183
1184 sc->hs_destroy = TRUE;
1185
1186 /*
1187 * At this point, all outbound traffic should be disabled. We
1188 * only allow inbound traffic (responses) to proceed so that

--- 5 unchanged lines hidden (view full) ---

1194 sc->hs_drain_notify = FALSE;
1195
1196 /*
1197 * Since we have already drained, we don't need to busy wait.
1198 * The call to close the channel will reset the callback
1199 * under the protection of the incoming channel lock.
1200 */
1201
1085 struct hv_sgl_node *sgl_node = NULL;
1086 int j = 0;
1087
1088 sc->hs_destroy = TRUE;
1089
1090 /*
1091 * At this point, all outbound traffic should be disabled. We
1092 * only allow inbound traffic (responses) to proceed so that

--- 5 unchanged lines hidden (view full) ---

1098 sc->hs_drain_notify = FALSE;
1099
1100 /*
1101 * Since we have already drained, we don't need to busy wait.
1102 * The call to close the channel will reset the callback
1103 * under the protection of the incoming channel lock.
1104 */
1105
1202 hv_vmbus_channel_close(hv_device->channel);
1106 hv_vmbus_channel_close(sc->hs_chan);
1203
1204 mtx_lock(&sc->hs_lock);
1205 while (!LIST_EMPTY(&sc->hs_free_list)) {
1206 reqp = LIST_FIRST(&sc->hs_free_list);
1207 LIST_REMOVE(reqp, link);
1208
1209 free(reqp, M_DEVBUF);
1210 }

--- 37 unchanged lines hidden (view full) ---

1248
1249 if (reqp->vstor_packet.vm_srb.cdb[0] != opcode) {
1250 return;
1251 }
1252
1253 if (wait) {
1254 mtx_lock(&reqp->event.mtx);
1255 }
1107
1108 mtx_lock(&sc->hs_lock);
1109 while (!LIST_EMPTY(&sc->hs_free_list)) {
1110 reqp = LIST_FIRST(&sc->hs_free_list);
1111 LIST_REMOVE(reqp, link);
1112
1113 free(reqp, M_DEVBUF);
1114 }

--- 37 unchanged lines hidden (view full) ---

1152
1153 if (reqp->vstor_packet.vm_srb.cdb[0] != opcode) {
1154 return;
1155 }
1156
1157 if (wait) {
1158 mtx_lock(&reqp->event.mtx);
1159 }
1256 ret = hv_storvsc_io_request(sc->hs_dev, reqp);
1160 ret = hv_storvsc_io_request(sc, reqp);
1257 if (ret != 0) {
1258 if (wait) {
1259 mtx_unlock(&reqp->event.mtx);
1260 }
1261 printf("%s: io_request failed with %d.\n",
1262 __func__, ret);
1263 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
1264 mtx_lock(&sc->hs_lock);

--- 94 unchanged lines hidden (view full) ---

1359 */
1360static void
1361storvsc_poll(struct cam_sim *sim)
1362{
1363 struct storvsc_softc *sc = cam_sim_softc(sim);
1364
1365 mtx_assert(&sc->hs_lock, MA_OWNED);
1366 mtx_unlock(&sc->hs_lock);
1161 if (ret != 0) {
1162 if (wait) {
1163 mtx_unlock(&reqp->event.mtx);
1164 }
1165 printf("%s: io_request failed with %d.\n",
1166 __func__, ret);
1167 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
1168 mtx_lock(&sc->hs_lock);

--- 94 unchanged lines hidden (view full) ---

1263 */
1264static void
1265storvsc_poll(struct cam_sim *sim)
1266{
1267 struct storvsc_softc *sc = cam_sim_softc(sim);
1268
1269 mtx_assert(&sc->hs_lock, MA_OWNED);
1270 mtx_unlock(&sc->hs_lock);
1367 hv_storvsc_on_channel_callback(sc->hs_dev->channel);
1271 hv_storvsc_on_channel_callback(sc->hs_chan);
1368 mtx_lock(&sc->hs_lock);
1369}
1370
1371/**
1372 * @brief StorVSC device action function
1373 *
1374 * This function is responsible for handling SCSI operations which
1375 * are passed from the CAM layer. The requests are in the form of

--- 68 unchanged lines hidden (view full) ---

1444 case XPT_CALC_GEOMETRY:{
1445 cam_calc_geometry(&ccb->ccg, 1);
1446 xpt_done(ccb);
1447 return;
1448 }
1449 case XPT_RESET_BUS:
1450 case XPT_RESET_DEV:{
1451#if HVS_HOST_RESET
1272 mtx_lock(&sc->hs_lock);
1273}
1274
1275/**
1276 * @brief StorVSC device action function
1277 *
1278 * This function is responsible for handling SCSI operations which
1279 * are passed from the CAM layer. The requests are in the form of

--- 68 unchanged lines hidden (view full) ---

1348 case XPT_CALC_GEOMETRY:{
1349 cam_calc_geometry(&ccb->ccg, 1);
1350 xpt_done(ccb);
1351 return;
1352 }
1353 case XPT_RESET_BUS:
1354 case XPT_RESET_DEV:{
1355#if HVS_HOST_RESET
1452 if ((res = hv_storvsc_host_reset(sc->hs_dev)) != 0) {
1356 if ((res = hv_storvsc_host_reset(sc)) != 0) {
1453 xpt_print(ccb->ccb_h.path,
1454 "hv_storvsc_host_reset failed with %d\n", res);
1455 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
1456 xpt_done(ccb);
1457 return;
1458 }
1459 ccb->ccb_h.status = CAM_REQ_CMP;
1460 xpt_done(ccb);

--- 56 unchanged lines hidden (view full) ---

1517 return;
1518 default:
1519 break;
1520 }
1521#endif /* HVS_TIMEOUT_TEST */
1522 }
1523#endif
1524
1357 xpt_print(ccb->ccb_h.path,
1358 "hv_storvsc_host_reset failed with %d\n", res);
1359 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
1360 xpt_done(ccb);
1361 return;
1362 }
1363 ccb->ccb_h.status = CAM_REQ_CMP;
1364 xpt_done(ccb);

--- 56 unchanged lines hidden (view full) ---

1421 return;
1422 default:
1423 break;
1424 }
1425#endif /* HVS_TIMEOUT_TEST */
1426 }
1427#endif
1428
1525 if ((res = hv_storvsc_io_request(sc->hs_dev, reqp)) != 0) {
1429 if ((res = hv_storvsc_io_request(sc, reqp)) != 0) {
1526 xpt_print(ccb->ccb_h.path,
1527 "hv_storvsc_io_request failed with %d\n", res);
1528 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
1529 storvsc_free_request(sc, reqp);
1530 xpt_done(ccb);
1531 return;
1532 }
1533 return;

--- 609 unchanged lines hidden (view full) ---

2143 * SCSI or BlkVSC (paravirtual IDE) device.
2144 *
2145 * @param dev a device
2146 * returns an enum
2147 */
2148static enum hv_storage_type
2149storvsc_get_storage_type(device_t dev)
2150{
1430 xpt_print(ccb->ccb_h.path,
1431 "hv_storvsc_io_request failed with %d\n", res);
1432 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
1433 storvsc_free_request(sc, reqp);
1434 xpt_done(ccb);
1435 return;
1436 }
1437 return;

--- 609 unchanged lines hidden (view full) ---

2047 * SCSI or BlkVSC (paravirtual IDE) device.
2048 *
2049 * @param dev a device
2050 * returns an enum
2051 */
2052static enum hv_storage_type
2053storvsc_get_storage_type(device_t dev)
2054{
2151 const char *p = vmbus_get_type(dev);
2055 device_t parent = device_get_parent(dev);
2152
2056
2153 if (!memcmp(p, &gBlkVscDeviceType, sizeof(hv_guid))) {
2057 if (VMBUS_PROBE_GUID(parent, dev, &gBlkVscDeviceType) == 0)
2154 return DRIVER_BLKVSC;
2058 return DRIVER_BLKVSC;
2155 } else if (!memcmp(p, &gStorVscDeviceType, sizeof(hv_guid))) {
2059 if (VMBUS_PROBE_GUID(parent, dev, &gStorVscDeviceType) == 0)
2156 return DRIVER_STORVSC;
2060 return DRIVER_STORVSC;
2157 }
2158 return (DRIVER_UNKNOWN);
2061 return DRIVER_UNKNOWN;
2159}
2062}
2160