Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
Show First 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | |||||
/** | /** | ||||
* @brief Process the offer by creating a channel/device | * @brief Process the offer by creating a channel/device | ||||
* associated with this offer | * associated with this offer | ||||
*/ | */ | ||||
static void | static void | ||||
vmbus_channel_process_offer(hv_vmbus_channel *new_channel) | vmbus_channel_process_offer(hv_vmbus_channel *new_channel) | ||||
{ | { | ||||
struct vmbus_softc *sc = new_channel->vmbus_sc; | |||||
hv_vmbus_channel* channel; | hv_vmbus_channel* channel; | ||||
uint32_t relid; | uint32_t relid; | ||||
relid = new_channel->offer_msg.child_rel_id; | relid = new_channel->offer_msg.child_rel_id; | ||||
/* | /* | ||||
* Make sure this is a new offer | * Make sure this is a new offer | ||||
*/ | */ | ||||
mtx_lock(&hv_vmbus_g_connection.channel_lock); | mtx_lock(&sc->vmbus_chlist_lock); | ||||
if (relid == 0) { | if (relid == 0) { | ||||
/* | /* | ||||
* XXX channel0 will not be processed; skip it. | * XXX channel0 will not be processed; skip it. | ||||
*/ | */ | ||||
printf("VMBUS: got channel0 offer\n"); | printf("VMBUS: got channel0 offer\n"); | ||||
} else { | } else { | ||||
hv_vmbus_g_connection.channels[relid] = new_channel; | hv_vmbus_g_connection.channels[relid] = new_channel; | ||||
} | } | ||||
TAILQ_FOREACH(channel, &hv_vmbus_g_connection.channel_anchor, | TAILQ_FOREACH(channel, &sc->vmbus_chlist, ch_link) { | ||||
list_entry) { | |||||
if (memcmp(&channel->offer_msg.offer.interface_type, | if (memcmp(&channel->offer_msg.offer.interface_type, | ||||
&new_channel->offer_msg.offer.interface_type, | &new_channel->offer_msg.offer.interface_type, | ||||
sizeof(hv_guid)) == 0 && | sizeof(hv_guid)) == 0 && | ||||
memcmp(&channel->offer_msg.offer.interface_instance, | memcmp(&channel->offer_msg.offer.interface_instance, | ||||
&new_channel->offer_msg.offer.interface_instance, | &new_channel->offer_msg.offer.interface_instance, | ||||
sizeof(hv_guid)) == 0) | sizeof(hv_guid)) == 0) | ||||
break; | break; | ||||
} | } | ||||
if (channel == NULL) { | if (channel == NULL) { | ||||
/* Install the new primary channel */ | /* Install the new primary channel */ | ||||
TAILQ_INSERT_TAIL(&hv_vmbus_g_connection.channel_anchor, | TAILQ_INSERT_TAIL(&sc->vmbus_chlist, new_channel, ch_link); | ||||
new_channel, list_entry); | |||||
} | } | ||||
mtx_unlock(&hv_vmbus_g_connection.channel_lock); | mtx_unlock(&sc->vmbus_chlist_lock); | ||||
if (channel != NULL) { | if (channel != NULL) { | ||||
/* | /* | ||||
* Check if this is a sub channel. | * Check if this is a sub channel. | ||||
*/ | */ | ||||
if (new_channel->offer_msg.offer.sub_channel_index != 0) { | if (new_channel->offer_msg.offer.sub_channel_index != 0) { | ||||
/* | /* | ||||
* It is a sub channel offer, process it. | * It is a sub channel offer, process it. | ||||
*/ | */ | ||||
new_channel->primary_channel = channel; | new_channel->primary_channel = channel; | ||||
new_channel->device = channel->device; | new_channel->device = channel->device; | ||||
mtx_lock(&channel->sc_lock); | mtx_lock(&channel->sc_lock); | ||||
TAILQ_INSERT_TAIL(&channel->sc_list_anchor, | TAILQ_INSERT_TAIL(&channel->sc_list_anchor, | ||||
new_channel, sc_list_entry); | new_channel, sc_list_entry); | ||||
mtx_unlock(&channel->sc_lock); | mtx_unlock(&channel->sc_lock); | ||||
if (bootverbose) { | if (bootverbose) { | ||||
printf("VMBUS get multi-channel offer, " | printf("VMBUS get multi-channel offer, " | ||||
"rel=%u, sub=%u\n", | "rel=%u, sub=%u\n", | ||||
new_channel->offer_msg.child_rel_id, | new_channel->offer_msg.child_rel_id, | ||||
new_channel->offer_msg.offer.sub_channel_index); | new_channel->offer_msg.offer.sub_channel_index); | ||||
} | } | ||||
/* Insert new channel into channel_anchor. */ | /* | ||||
mtx_lock(&hv_vmbus_g_connection.channel_lock); | * Insert the new channel to the end of the global | ||||
TAILQ_INSERT_TAIL(&hv_vmbus_g_connection.channel_anchor, | * channel list. | ||||
new_channel, list_entry); | * | ||||
mtx_unlock(&hv_vmbus_g_connection.channel_lock); | * NOTE: | ||||
* The new sub-channel MUST be inserted AFTER it's | |||||
* primary channel, so that the primary channel will | |||||
* be found in the above loop for its baby siblings. | |||||
*/ | |||||
mtx_lock(&sc->vmbus_chlist_lock); | |||||
TAILQ_INSERT_TAIL(&sc->vmbus_chlist, new_channel, | |||||
ch_link); | |||||
mtx_unlock(&sc->vmbus_chlist_lock); | |||||
if(bootverbose) | if(bootverbose) | ||||
printf("VMBUS: new multi-channel offer <%p>, " | printf("VMBUS: new multi-channel offer <%p>, " | ||||
"its primary channel is <%p>.\n", | "its primary channel is <%p>.\n", | ||||
new_channel, new_channel->primary_channel); | new_channel, new_channel->primary_channel); | ||||
new_channel->state = HV_CHANNEL_OPEN_STATE; | new_channel->state = HV_CHANNEL_OPEN_STATE; | ||||
▲ Show 20 Lines • Show All 189 Lines • ▼ Show 20 Lines | vmbus_channel_on_offers_delivered(struct vmbus_softc *sc, | ||||
/* No more new channels for the channel request. */ | /* No more new channels for the channel request. */ | ||||
vmbus_scan_done(sc); | vmbus_scan_done(sc); | ||||
} | } | ||||
/** | /** | ||||
* @brief Release channels that are unattached/unconnected (i.e., no drivers associated) | * @brief Release channels that are unattached/unconnected (i.e., no drivers associated) | ||||
*/ | */ | ||||
void | void | ||||
hv_vmbus_release_unattached_channels(void) | hv_vmbus_release_unattached_channels(struct vmbus_softc *sc) | ||||
{ | { | ||||
hv_vmbus_channel *channel; | hv_vmbus_channel *channel; | ||||
mtx_lock(&hv_vmbus_g_connection.channel_lock); | mtx_lock(&sc->vmbus_chlist_lock); | ||||
while (!TAILQ_EMPTY(&hv_vmbus_g_connection.channel_anchor)) { | while (!TAILQ_EMPTY(&sc->vmbus_chlist)) { | ||||
channel = TAILQ_FIRST(&hv_vmbus_g_connection.channel_anchor); | channel = TAILQ_FIRST(&sc->vmbus_chlist); | ||||
TAILQ_REMOVE(&hv_vmbus_g_connection.channel_anchor, | TAILQ_REMOVE(&sc->vmbus_chlist, channel, ch_link); | ||||
channel, list_entry); | |||||
if (HV_VMBUS_CHAN_ISPRIMARY(channel)) { | if (HV_VMBUS_CHAN_ISPRIMARY(channel)) { | ||||
/* Only primary channel owns the hv_device */ | /* Only primary channel owns the hv_device */ | ||||
hv_vmbus_child_device_unregister(channel->device); | hv_vmbus_child_device_unregister(channel->device); | ||||
} | } | ||||
hv_vmbus_free_vmbus_channel(channel); | hv_vmbus_free_vmbus_channel(channel); | ||||
} | } | ||||
bzero(hv_vmbus_g_connection.channels, | bzero(hv_vmbus_g_connection.channels, | ||||
sizeof(hv_vmbus_channel*) * VMBUS_CHAN_MAX); | sizeof(hv_vmbus_channel*) * VMBUS_CHAN_MAX); | ||||
mtx_unlock(&hv_vmbus_g_connection.channel_lock); | |||||
mtx_unlock(&sc->vmbus_chlist_lock); | |||||
} | } | ||||
/** | /** | ||||
* @brief Select the best outgoing channel | * @brief Select the best outgoing channel | ||||
* | * | ||||
* The channel whose vcpu binding is closest to the currect vcpu will | * The channel whose vcpu binding is closest to the currect vcpu will | ||||
* be selected. | * be selected. | ||||
* If no multi-channel, always select primary channel | * If no multi-channel, always select primary channel | ||||
▲ Show 20 Lines • Show All 105 Lines • Show Last 20 Lines |