Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
Show First 20 Lines • Show All 361 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
vmbus_chan_detach_task(void *xchan, int pending __unused) | vmbus_chan_detach_task(void *xchan, int pending __unused) | ||||
{ | { | ||||
struct hv_vmbus_channel *chan = xchan; | struct hv_vmbus_channel *chan = xchan; | ||||
if (HV_VMBUS_CHAN_ISPRIMARY(chan)) { | if (HV_VMBUS_CHAN_ISPRIMARY(chan)) { | ||||
/* Only primary channel owns the hv_device */ | /* Only primary channel owns the hv_device */ | ||||
hv_vmbus_child_device_unregister(chan->device); | hv_vmbus_child_device_unregister(chan->device); | ||||
/* NOTE: DO NOT free primary channel for now */ | |||||
} else { | |||||
struct vmbus_softc *sc = chan->vmbus_sc; | |||||
struct hv_vmbus_channel *pri_chan = chan->primary_channel; | |||||
struct vmbus_chanmsg_chfree *req; | |||||
struct vmbus_msghc *mh; | |||||
int error; | |||||
mh = vmbus_msghc_get(sc, sizeof(*req)); | |||||
if (mh == NULL) { | |||||
device_printf(sc->vmbus_dev, | |||||
"can not get msg hypercall for chfree(chan%u)\n", | |||||
chan->offer_msg.child_rel_id); | |||||
goto remove; | |||||
} | } | ||||
req = vmbus_msghc_dataptr(mh); | |||||
req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHFREE; | |||||
req->chm_chanid = chan->offer_msg.child_rel_id; | |||||
error = vmbus_msghc_exec_noresult(mh); | |||||
vmbus_msghc_put(sc, mh); | |||||
if (error) { | |||||
device_printf(sc->vmbus_dev, | |||||
"chfree(chan%u) failed: %d", | |||||
chan->offer_msg.child_rel_id, error); | |||||
/* NOTE: Move on! */ | |||||
} else { | |||||
if (bootverbose) { | |||||
device_printf(sc->vmbus_dev, "chan%u freed\n", | |||||
chan->offer_msg.child_rel_id); | |||||
} | } | ||||
} | |||||
remove: | |||||
mtx_lock(&sc->vmbus_chlist_lock); | |||||
TAILQ_REMOVE(&sc->vmbus_chlist, chan, ch_link); | |||||
mtx_unlock(&sc->vmbus_chlist_lock); | |||||
mtx_lock(&pri_chan->sc_lock); | |||||
TAILQ_REMOVE(&pri_chan->sc_list_anchor, chan, sc_list_entry); | |||||
KASSERT(pri_chan->subchan_cnt > 0, | |||||
("invalid subchan_cnt %d", pri_chan->subchan_cnt)); | |||||
pri_chan->subchan_cnt--; | |||||
mtx_unlock(&pri_chan->sc_lock); | |||||
wakeup(pri_chan); | |||||
hv_vmbus_free_vmbus_channel(chan); | |||||
} | |||||
} | |||||
/** | /** | ||||
* | * | ||||
* @brief Invoked when all offers have been delivered. | * @brief Invoked when all offers have been delivered. | ||||
*/ | */ | ||||
static void | static void | ||||
vmbus_channel_on_offers_delivered(struct vmbus_softc *sc, | vmbus_channel_on_offers_delivered(struct vmbus_softc *sc, | ||||
const struct vmbus_message *msg __unused) | const struct vmbus_message *msg __unused) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | vmbus_get_subchan(struct hv_vmbus_channel *pri_chan, int subchan_cnt) | ||||
return ret; | return ret; | ||||
} | } | ||||
void | void | ||||
vmbus_rel_subchan(struct hv_vmbus_channel **subchan, int subchan_cnt __unused) | vmbus_rel_subchan(struct hv_vmbus_channel **subchan, int subchan_cnt __unused) | ||||
{ | { | ||||
free(subchan, M_TEMP); | free(subchan, M_TEMP); | ||||
} | |||||
void | |||||
vmbus_drain_subchan(struct hv_vmbus_channel *pri_chan) | |||||
{ | |||||
mtx_lock(&pri_chan->sc_lock); | |||||
while (pri_chan->subchan_cnt > 0) | |||||
mtx_sleep(pri_chan, &pri_chan->sc_lock, 0, "dsubch", 0); | |||||
mtx_unlock(&pri_chan->sc_lock); | |||||
} | } | ||||
void | void | ||||
vmbus_chan_msgproc(struct vmbus_softc *sc, const struct vmbus_message *msg) | vmbus_chan_msgproc(struct vmbus_softc *sc, const struct vmbus_message *msg) | ||||
{ | { | ||||
vmbus_chanmsg_proc_t msg_proc; | vmbus_chanmsg_proc_t msg_proc; | ||||
uint32_t msg_type; | uint32_t msg_type; | ||||
Show All 11 Lines |