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 --- |