Deleted Added
full compact
vmbus.c (307475) vmbus.c (307599)
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

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

25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*
30 * VM Bus Driver Implementation
31 */
32#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

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

25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*
30 * VM Bus Driver Implementation
31 */
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: stable/11/sys/dev/hyperv/vmbus/vmbus.c 307475 2016-10-17 05:53:38Z sephe $");
33__FBSDID("$FreeBSD: stable/11/sys/dev/hyperv/vmbus/vmbus.c 307599 2016-10-19 02:24:17Z sephe $");
34
35#include <sys/param.h>
36#include <sys/bus.h>
37#include <sys/kernel.h>
38#include <sys/lock.h>
39#include <sys/malloc.h>
40#include <sys/module.h>
41#include <sys/mutex.h>

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

78static int vmbus_probe_guid_method(device_t, device_t,
79 const struct hyperv_guid *);
80
81static int vmbus_init(struct vmbus_softc *);
82static int vmbus_connect(struct vmbus_softc *, uint32_t);
83static int vmbus_req_channels(struct vmbus_softc *sc);
84static void vmbus_disconnect(struct vmbus_softc *);
85static int vmbus_scan(struct vmbus_softc *);
34
35#include <sys/param.h>
36#include <sys/bus.h>
37#include <sys/kernel.h>
38#include <sys/lock.h>
39#include <sys/malloc.h>
40#include <sys/module.h>
41#include <sys/mutex.h>

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

78static int vmbus_probe_guid_method(device_t, device_t,
79 const struct hyperv_guid *);
80
81static int vmbus_init(struct vmbus_softc *);
82static int vmbus_connect(struct vmbus_softc *, uint32_t);
83static int vmbus_req_channels(struct vmbus_softc *sc);
84static void vmbus_disconnect(struct vmbus_softc *);
85static int vmbus_scan(struct vmbus_softc *);
86static void vmbus_scan_wait(struct vmbus_softc *);
87static void vmbus_scan_newchan(struct vmbus_softc *);
88static void vmbus_scan_newdev(struct vmbus_softc *);
86static void vmbus_scan_teardown(struct vmbus_softc *);
89static void vmbus_scan_done(struct vmbus_softc *,
90 const struct vmbus_message *);
91static void vmbus_chanmsg_handle(struct vmbus_softc *,
92 const struct vmbus_message *);
93static void vmbus_msg_task(void *, int);
94static void vmbus_synic_setup(void *);
95static void vmbus_synic_teardown(void *);
96static int vmbus_sysctl_version(SYSCTL_HANDLER_ARGS);

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

388
389 error = vmbus_msghc_exec_noresult(mh);
390 vmbus_msghc_put(sc, mh);
391
392 return error;
393}
394
395static void
87static void vmbus_scan_done(struct vmbus_softc *,
88 const struct vmbus_message *);
89static void vmbus_chanmsg_handle(struct vmbus_softc *,
90 const struct vmbus_message *);
91static void vmbus_msg_task(void *, int);
92static void vmbus_synic_setup(void *);
93static void vmbus_synic_teardown(void *);
94static int vmbus_sysctl_version(SYSCTL_HANDLER_ARGS);

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

386
387 error = vmbus_msghc_exec_noresult(mh);
388 vmbus_msghc_put(sc, mh);
389
390 return error;
391}
392
393static void
396vmbus_scan_newchan(struct vmbus_softc *sc)
394vmbus_scan_done_task(void *xsc, int pending __unused)
397{
395{
398 mtx_lock(&sc->vmbus_scan_lock);
399 if ((sc->vmbus_scan_chcnt & VMBUS_SCAN_CHCNT_DONE) == 0)
400 sc->vmbus_scan_chcnt++;
401 mtx_unlock(&sc->vmbus_scan_lock);
396 struct vmbus_softc *sc = xsc;
397
398 mtx_lock(&Giant);
399 sc->vmbus_scandone = true;
400 mtx_unlock(&Giant);
401 wakeup(&sc->vmbus_scandone);
402}
403
404static void
405vmbus_scan_done(struct vmbus_softc *sc,
406 const struct vmbus_message *msg __unused)
407{
402}
403
404static void
405vmbus_scan_done(struct vmbus_softc *sc,
406 const struct vmbus_message *msg __unused)
407{
408 mtx_lock(&sc->vmbus_scan_lock);
409 sc->vmbus_scan_chcnt |= VMBUS_SCAN_CHCNT_DONE;
410 mtx_unlock(&sc->vmbus_scan_lock);
411 wakeup(&sc->vmbus_scan_chcnt);
412}
413
408
414static void
415vmbus_scan_newdev(struct vmbus_softc *sc)
416{
417 mtx_lock(&sc->vmbus_scan_lock);
418 sc->vmbus_scan_devcnt++;
419 mtx_unlock(&sc->vmbus_scan_lock);
420 wakeup(&sc->vmbus_scan_devcnt);
409 taskqueue_enqueue(sc->vmbus_devtq, &sc->vmbus_scandone_task);
421}
422
410}
411
423static void
424vmbus_scan_wait(struct vmbus_softc *sc)
425{
426 uint32_t chancnt;
427
428 mtx_lock(&sc->vmbus_scan_lock);
429 while ((sc->vmbus_scan_chcnt & VMBUS_SCAN_CHCNT_DONE) == 0) {
430 mtx_sleep(&sc->vmbus_scan_chcnt, &sc->vmbus_scan_lock, 0,
431 "waitch", 0);
432 }
433 chancnt = sc->vmbus_scan_chcnt & ~VMBUS_SCAN_CHCNT_DONE;
434
435 while (sc->vmbus_scan_devcnt != chancnt) {
436 mtx_sleep(&sc->vmbus_scan_devcnt, &sc->vmbus_scan_lock, 0,
437 "waitdev", 0);
438 }
439 mtx_unlock(&sc->vmbus_scan_lock);
440}
441
442static int
443vmbus_scan(struct vmbus_softc *sc)
444{
445 int error;
446
447 /*
412static int
413vmbus_scan(struct vmbus_softc *sc)
414{
415 int error;
416
417 /*
418 * Identify, probe and attach for non-channel devices.
419 */
420 bus_generic_probe(sc->vmbus_dev);
421 bus_generic_attach(sc->vmbus_dev);
422
423 /*
424 * This taskqueue serializes vmbus devices' attach and detach
425 * for channel offer and rescind messages.
426 */
427 sc->vmbus_devtq = taskqueue_create("vmbus dev", M_WAITOK,
428 taskqueue_thread_enqueue, &sc->vmbus_devtq);
429 taskqueue_start_threads(&sc->vmbus_devtq, 1, PI_NET, "vmbusdev");
430 TASK_INIT(&sc->vmbus_scandone_task, 0, vmbus_scan_done_task, sc);
431
432 /*
433 * This taskqueue handles sub-channel detach, so that vmbus
434 * device's detach running in vmbus_devtq can drain its sub-
435 * channels.
436 */
437 sc->vmbus_subchtq = taskqueue_create("vmbus subch", M_WAITOK,
438 taskqueue_thread_enqueue, &sc->vmbus_subchtq);
439 taskqueue_start_threads(&sc->vmbus_subchtq, 1, PI_NET, "vmbussch");
440
441 /*
448 * Start vmbus scanning.
449 */
450 error = vmbus_req_channels(sc);
451 if (error) {
452 device_printf(sc->vmbus_dev, "channel request failed: %d\n",
453 error);
442 * Start vmbus scanning.
443 */
444 error = vmbus_req_channels(sc);
445 if (error) {
446 device_printf(sc->vmbus_dev, "channel request failed: %d\n",
447 error);
454 return error;
448 return (error);
455 }
456
457 /*
449 }
450
451 /*
458 * Wait for all devices are added to vmbus.
452 * Wait for all vmbus devices from the initial channel offers to be
453 * attached.
459 */
454 */
460 vmbus_scan_wait(sc);
455 GIANT_REQUIRED;
456 while (!sc->vmbus_scandone)
457 mtx_sleep(&sc->vmbus_scandone, &Giant, 0, "vmbusdev", 0);
461
458
462 /*
463 * Identify, probe and attach.
464 */
465 bus_generic_probe(sc->vmbus_dev);
466 bus_generic_attach(sc->vmbus_dev);
467
468 if (bootverbose) {
469 device_printf(sc->vmbus_dev, "device scan, probe and attach "
470 "done\n");
471 }
459 if (bootverbose) {
460 device_printf(sc->vmbus_dev, "device scan, probe and attach "
461 "done\n");
462 }
472 return 0;
463 return (0);
473}
474
475static void
464}
465
466static void
467vmbus_scan_teardown(struct vmbus_softc *sc)
468{
469
470 GIANT_REQUIRED;
471 if (sc->vmbus_devtq != NULL) {
472 mtx_unlock(&Giant);
473 taskqueue_free(sc->vmbus_devtq);
474 mtx_lock(&Giant);
475 sc->vmbus_devtq = NULL;
476 }
477 if (sc->vmbus_subchtq != NULL) {
478 mtx_unlock(&Giant);
479 taskqueue_free(sc->vmbus_subchtq);
480 mtx_lock(&Giant);
481 sc->vmbus_subchtq = NULL;
482 }
483}
484
485static void
476vmbus_chanmsg_handle(struct vmbus_softc *sc, const struct vmbus_message *msg)
477{
478 vmbus_chanmsg_proc_t msg_proc;
479 uint32_t msg_type;
480
481 msg_type = ((const struct vmbus_chanmsg_hdr *)msg->msg_data)->chm_type;
482 if (msg_type >= VMBUS_CHANMSG_TYPE_MAX) {
483 device_printf(sc->vmbus_dev, "unknown message type 0x%x\n",

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

913 return (0);
914}
915
916int
917vmbus_add_child(struct vmbus_channel *chan)
918{
919 struct vmbus_softc *sc = chan->ch_vmbus;
920 device_t parent = sc->vmbus_dev;
486vmbus_chanmsg_handle(struct vmbus_softc *sc, const struct vmbus_message *msg)
487{
488 vmbus_chanmsg_proc_t msg_proc;
489 uint32_t msg_type;
490
491 msg_type = ((const struct vmbus_chanmsg_hdr *)msg->msg_data)->chm_type;
492 if (msg_type >= VMBUS_CHANMSG_TYPE_MAX) {
493 device_printf(sc->vmbus_dev, "unknown message type 0x%x\n",

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

923 return (0);
924}
925
926int
927vmbus_add_child(struct vmbus_channel *chan)
928{
929 struct vmbus_softc *sc = chan->ch_vmbus;
930 device_t parent = sc->vmbus_dev;
921 int error = 0;
922
931
923 /* New channel has been offered */
924 vmbus_scan_newchan(sc);
932 mtx_lock(&Giant);
925
926 chan->ch_dev = device_add_child(parent, NULL, -1);
927 if (chan->ch_dev == NULL) {
933
934 chan->ch_dev = device_add_child(parent, NULL, -1);
935 if (chan->ch_dev == NULL) {
936 mtx_unlock(&Giant);
928 device_printf(parent, "device_add_child for chan%u failed\n",
929 chan->ch_id);
937 device_printf(parent, "device_add_child for chan%u failed\n",
938 chan->ch_id);
930 error = ENXIO;
931 goto done;
939 return (ENXIO);
932 }
933 device_set_ivars(chan->ch_dev, chan);
940 }
941 device_set_ivars(chan->ch_dev, chan);
942 device_probe_and_attach(chan->ch_dev);
934
943
935done:
936 /* New device has been/should be added to vmbus. */
937 vmbus_scan_newdev(sc);
938 return error;
944 mtx_unlock(&Giant);
945 return (0);
939}
940
941int
942vmbus_delete_child(struct vmbus_channel *chan)
943{
946}
947
948int
949vmbus_delete_child(struct vmbus_channel *chan)
950{
944 int error;
951 int error = 0;
945
952
946 if (chan->ch_dev == NULL) {
947 /* Failed to add a device. */
948 return 0;
949 }
950
951 /*
952 * XXXKYS: Ensure that this is the opposite of
953 * device_add_child()
954 */
955 mtx_lock(&Giant);
953 mtx_lock(&Giant);
956 error = device_delete_child(chan->ch_vmbus->vmbus_dev, chan->ch_dev);
954 if (chan->ch_dev != NULL) {
955 error = device_delete_child(chan->ch_vmbus->vmbus_dev,
956 chan->ch_dev);
957 }
957 mtx_unlock(&Giant);
958 mtx_unlock(&Giant);
958
959 return error;
959 return (error);
960}
961
962static int
963vmbus_sysctl_version(SYSCTL_HANDLER_ARGS)
964{
965 struct vmbus_softc *sc = arg1;
966 char verstr[16];
967

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

1023 struct sysctl_oid_list *child;
1024 struct sysctl_ctx_list *ctx;
1025 int ret;
1026
1027 if (sc->vmbus_flags & VMBUS_FLAG_ATTACHED)
1028 return (0);
1029 sc->vmbus_flags |= VMBUS_FLAG_ATTACHED;
1030
960}
961
962static int
963vmbus_sysctl_version(SYSCTL_HANDLER_ARGS)
964{
965 struct vmbus_softc *sc = arg1;
966 char verstr[16];
967

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

1023 struct sysctl_oid_list *child;
1024 struct sysctl_ctx_list *ctx;
1025 int ret;
1026
1027 if (sc->vmbus_flags & VMBUS_FLAG_ATTACHED)
1028 return (0);
1029 sc->vmbus_flags |= VMBUS_FLAG_ATTACHED;
1030
1031 mtx_init(&sc->vmbus_scan_lock, "vmbus scan", NULL, MTX_DEF);
1032 sc->vmbus_gpadl = VMBUS_GPADL_START;
1033 mtx_init(&sc->vmbus_prichan_lock, "vmbus prichan", NULL, MTX_DEF);
1034 TAILQ_INIT(&sc->vmbus_prichans);
1031 sc->vmbus_gpadl = VMBUS_GPADL_START;
1032 mtx_init(&sc->vmbus_prichan_lock, "vmbus prichan", NULL, MTX_DEF);
1033 TAILQ_INIT(&sc->vmbus_prichans);
1034 mtx_init(&sc->vmbus_chan_lock, "vmbus channel", NULL, MTX_DEF);
1035 TAILQ_INIT(&sc->vmbus_chans);
1035 sc->vmbus_chmap = malloc(
1036 sizeof(struct vmbus_channel *) * VMBUS_CHAN_MAX, M_DEVBUF,
1037 M_WAITOK | M_ZERO);
1038
1039 /*
1040 * Create context for "post message" Hypercalls
1041 */
1042 sc->vmbus_xc = vmbus_xact_ctx_create(bus_get_dma_tag(sc->vmbus_dev),

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

1090 child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->vmbus_dev));
1091 SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "version",
1092 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
1093 vmbus_sysctl_version, "A", "vmbus version");
1094
1095 return (ret);
1096
1097cleanup:
1036 sc->vmbus_chmap = malloc(
1037 sizeof(struct vmbus_channel *) * VMBUS_CHAN_MAX, M_DEVBUF,
1038 M_WAITOK | M_ZERO);
1039
1040 /*
1041 * Create context for "post message" Hypercalls
1042 */
1043 sc->vmbus_xc = vmbus_xact_ctx_create(bus_get_dma_tag(sc->vmbus_dev),

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

1091 child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->vmbus_dev));
1092 SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "version",
1093 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
1094 vmbus_sysctl_version, "A", "vmbus version");
1095
1096 return (ret);
1097
1098cleanup:
1099 vmbus_scan_teardown(sc);
1098 vmbus_intr_teardown(sc);
1099 vmbus_dma_free(sc);
1100 if (sc->vmbus_xc != NULL) {
1101 vmbus_xact_ctx_destroy(sc->vmbus_xc);
1102 sc->vmbus_xc = NULL;
1103 }
1104 free(sc->vmbus_chmap, M_DEVBUF);
1100 vmbus_intr_teardown(sc);
1101 vmbus_dma_free(sc);
1102 if (sc->vmbus_xc != NULL) {
1103 vmbus_xact_ctx_destroy(sc->vmbus_xc);
1104 sc->vmbus_xc = NULL;
1105 }
1106 free(sc->vmbus_chmap, M_DEVBUF);
1105 mtx_destroy(&sc->vmbus_scan_lock);
1106 mtx_destroy(&sc->vmbus_prichan_lock);
1107 mtx_destroy(&sc->vmbus_prichan_lock);
1108 mtx_destroy(&sc->vmbus_chan_lock);
1107
1108 return (ret);
1109}
1110
1111static void
1112vmbus_event_proc_dummy(struct vmbus_softc *sc __unused, int cpu __unused)
1113{
1114}

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

1141 return (0);
1142}
1143
1144static int
1145vmbus_detach(device_t dev)
1146{
1147 struct vmbus_softc *sc = device_get_softc(dev);
1148
1109
1110 return (ret);
1111}
1112
1113static void
1114vmbus_event_proc_dummy(struct vmbus_softc *sc __unused, int cpu __unused)
1115{
1116}

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

1143 return (0);
1144}
1145
1146static int
1147vmbus_detach(device_t dev)
1148{
1149 struct vmbus_softc *sc = device_get_softc(dev);
1150
1151 bus_generic_detach(dev);
1149 vmbus_chan_destroy_all(sc);
1150
1152 vmbus_chan_destroy_all(sc);
1153
1154 vmbus_scan_teardown(sc);
1155
1151 vmbus_disconnect(sc);
1152
1153 if (sc->vmbus_flags & VMBUS_FLAG_SYNIC) {
1154 sc->vmbus_flags &= ~VMBUS_FLAG_SYNIC;
1155 smp_rendezvous(NULL, vmbus_synic_teardown, NULL, NULL);
1156 }
1157
1158 vmbus_intr_teardown(sc);
1159 vmbus_dma_free(sc);
1160
1161 if (sc->vmbus_xc != NULL) {
1162 vmbus_xact_ctx_destroy(sc->vmbus_xc);
1163 sc->vmbus_xc = NULL;
1164 }
1165
1166 free(sc->vmbus_chmap, M_DEVBUF);
1156 vmbus_disconnect(sc);
1157
1158 if (sc->vmbus_flags & VMBUS_FLAG_SYNIC) {
1159 sc->vmbus_flags &= ~VMBUS_FLAG_SYNIC;
1160 smp_rendezvous(NULL, vmbus_synic_teardown, NULL, NULL);
1161 }
1162
1163 vmbus_intr_teardown(sc);
1164 vmbus_dma_free(sc);
1165
1166 if (sc->vmbus_xc != NULL) {
1167 vmbus_xact_ctx_destroy(sc->vmbus_xc);
1168 sc->vmbus_xc = NULL;
1169 }
1170
1171 free(sc->vmbus_chmap, M_DEVBUF);
1167 mtx_destroy(&sc->vmbus_scan_lock);
1168 mtx_destroy(&sc->vmbus_prichan_lock);
1172 mtx_destroy(&sc->vmbus_prichan_lock);
1173 mtx_destroy(&sc->vmbus_chan_lock);
1169
1170 return (0);
1171}
1172
1173#ifndef EARLY_AP_STARTUP
1174
1175static void
1176vmbus_sysinit(void *arg __unused)

--- 23 unchanged lines hidden ---
1174
1175 return (0);
1176}
1177
1178#ifndef EARLY_AP_STARTUP
1179
1180static void
1181vmbus_sysinit(void *arg __unused)

--- 23 unchanged lines hidden ---