MFC 298569,298570,298571,298572,298574,298575,298613,298614,298615,298616,298617
298569 hyperv/channel: Remove the unnecessary 'new' flag MFC after: 1 week Sponsored by: Microsoft OSTC 298570 hyperv/channel: Minor style changes; no functional changes. MFC after: 1 week Sponsored by: Microsoft OSTC 298571 hyperv/channel: Remove unapplied comment MFC after: 1 week Sponsored by: Microsoft OSTC 298572 hyperv/channel: Log a warning about duplicated primary channel offer MFC after: 1 week Sponsored by: Microsoft OSTC 298574 hyperv/channel: Add functions to synchronize sub-channel offers MFC after: 1 week Sponsored by: Microsoft OSTC 298575 hyperv/hn: Synchronize sub-channel offers MFC after: 1 week Sponsored by: Microsoft OSTC 298613 hyperv/stor: Remove the useless hs_open_multi_channel This fixes the sub-channel offer race after Hyper-V device probe/attach is moved to vmbus SYSINIT/attach. MFC after: 1 week Sponsored by: Microsoft OSTC 298614 hyperv/stor: Synchronize sub-channel offers MFC after: 1 week Sponsored by: Microsoft OSTC 298615 hyperv/hn: Avoid sub-channel creation callback. Since the sub-channel offers are synchronized, we can do our own channel setup without using the sub-channel creation callback. This paves the way to whack the sub-channel creation callback. MFC after: 1 week Sponsored by: Microsoft OSTC 298616 hyperv/stor: Avoid sub-channel creation callback. Since the sub-channel offers are synchronized, we can do our own channel setup without using the sub-channel creation callback. This paves the way to whack the sub-channel creation callback. MFC after: 1 week Sponsored by: Microsoft OSTC 298617 hyperv/channel: Git rid of the sub-channel creation callback It is no longer used. MFC after: 1 week Sponsored by: Microsoft OSTC
This commit is contained in:
parent
38d6282446
commit
c01c285878
@ -691,7 +691,6 @@ typedef struct {
|
||||
} hv_vmbus_ring_buffer_info;
|
||||
|
||||
typedef void (*hv_vmbus_pfn_channel_callback)(void *context);
|
||||
typedef void (*hv_vmbus_sc_creation_callback)(void *context);
|
||||
|
||||
typedef enum {
|
||||
HV_CHANNEL_OFFER_STATE,
|
||||
@ -804,13 +803,6 @@ typedef struct hv_vmbus_channel {
|
||||
* response on the same channel.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Multi-channel creation callback. This callback will be called in
|
||||
* process context when a Multi-channel offer is received from the host.
|
||||
* The guest can open the Multi-channel in the context of this callback.
|
||||
*/
|
||||
hv_vmbus_sc_creation_callback sc_creation_callback;
|
||||
|
||||
struct mtx sc_lock;
|
||||
|
||||
/*
|
||||
@ -818,6 +810,7 @@ typedef struct hv_vmbus_channel {
|
||||
*/
|
||||
TAILQ_HEAD(, hv_vmbus_channel) sc_list_anchor;
|
||||
TAILQ_ENTRY(hv_vmbus_channel) sc_list_entry;
|
||||
int subchan_cnt;
|
||||
|
||||
/*
|
||||
* The primary channel this sub-channle belongs to.
|
||||
@ -914,6 +907,9 @@ int hv_vmbus_channel_teardown_gpdal(
|
||||
struct hv_vmbus_channel* vmbus_select_outgoing_channel(struct hv_vmbus_channel *promary);
|
||||
|
||||
void vmbus_channel_cpu_set(struct hv_vmbus_channel *chan, int cpu);
|
||||
struct hv_vmbus_channel **
|
||||
vmbus_get_subchan(struct hv_vmbus_channel *pri_chan, int subchan_cnt);
|
||||
void vmbus_rel_subchan(struct hv_vmbus_channel **subchan, int subchan_cnt);
|
||||
|
||||
/**
|
||||
* @brief Get physical address from virtual
|
||||
|
@ -660,30 +660,12 @@ hv_nv_disconnect_from_vsp(netvsc_dev *net_dev)
|
||||
hv_nv_destroy_send_buffer(net_dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback handler for subchannel offer
|
||||
* @@param context new subchannel
|
||||
*/
|
||||
static void
|
||||
hv_nv_subchan_callback(void *xchan)
|
||||
void
|
||||
hv_nv_subchan_attach(struct hv_vmbus_channel *chan)
|
||||
{
|
||||
struct hv_vmbus_channel *chan = xchan;
|
||||
netvsc_dev *net_dev;
|
||||
uint16_t chn_index = chan->offer_msg.offer.sub_channel_index;
|
||||
struct hv_device *device = chan->device;
|
||||
hn_softc_t *sc = device_get_softc(device->device);
|
||||
int ret;
|
||||
|
||||
net_dev = sc->net_dev;
|
||||
|
||||
if (chn_index >= net_dev->num_channel) {
|
||||
/* Would this ever happen? */
|
||||
return;
|
||||
}
|
||||
netvsc_subchan_callback(sc, chan);
|
||||
|
||||
chan->hv_chan_rdbuf = malloc(NETVSC_PACKET_SIZE, M_NETVSC, M_WAITOK);
|
||||
ret = hv_vmbus_channel_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE,
|
||||
hv_vmbus_channel_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE,
|
||||
NETVSC_DEVICE_RING_BUFFER_SIZE, NULL, 0,
|
||||
hv_nv_on_channel_callback, chan);
|
||||
}
|
||||
@ -720,7 +702,6 @@ hv_nv_on_device_add(struct hv_device *device, void *additional_info)
|
||||
free(chan->hv_chan_rdbuf, M_NETVSC);
|
||||
goto cleanup;
|
||||
}
|
||||
chan->sc_creation_callback = hv_nv_subchan_callback;
|
||||
|
||||
/*
|
||||
* Connect with the NetVsp
|
||||
|
@ -1267,6 +1267,7 @@ int hv_nv_on_device_remove(struct hv_device *device,
|
||||
boolean_t destroy_channel);
|
||||
int hv_nv_on_send(struct hv_vmbus_channel *chan, netvsc_packet *pkt);
|
||||
int hv_nv_get_next_send_section(netvsc_dev *net_dev);
|
||||
void hv_nv_subchan_attach(struct hv_vmbus_channel *chan);
|
||||
|
||||
#endif /* __HV_NET_VSC_H__ */
|
||||
|
||||
|
@ -336,6 +336,7 @@ static void hn_create_rx_data(struct hn_softc *sc, int);
|
||||
static void hn_destroy_rx_data(struct hn_softc *sc);
|
||||
static void hn_set_tx_chimney_size(struct hn_softc *, int);
|
||||
static void hn_channel_attach(struct hn_softc *, struct hv_vmbus_channel *);
|
||||
static void hn_subchan_attach(struct hn_softc *, struct hv_vmbus_channel *);
|
||||
|
||||
static int hn_transmit(struct ifnet *, struct mbuf *);
|
||||
static void hn_xmit_qflush(struct ifnet *);
|
||||
@ -438,7 +439,7 @@ static int
|
||||
netvsc_attach(device_t dev)
|
||||
{
|
||||
struct hv_device *device_ctx = vmbus_get_devctx(dev);
|
||||
struct hv_vmbus_channel *chan;
|
||||
struct hv_vmbus_channel *pri_chan;
|
||||
netvsc_device_info device_info;
|
||||
hn_softc_t *sc;
|
||||
int unit = device_get_unit(dev);
|
||||
@ -518,12 +519,12 @@ netvsc_attach(device_t dev)
|
||||
/*
|
||||
* Associate the first TX/RX ring w/ the primary channel.
|
||||
*/
|
||||
chan = device_ctx->channel;
|
||||
KASSERT(HV_VMBUS_CHAN_ISPRIMARY(chan), ("not primary channel"));
|
||||
KASSERT(chan->offer_msg.offer.sub_channel_index == 0,
|
||||
pri_chan = device_ctx->channel;
|
||||
KASSERT(HV_VMBUS_CHAN_ISPRIMARY(pri_chan), ("not primary channel"));
|
||||
KASSERT(pri_chan->offer_msg.offer.sub_channel_index == 0,
|
||||
("primary channel subidx %u",
|
||||
chan->offer_msg.offer.sub_channel_index));
|
||||
hn_channel_attach(sc, chan);
|
||||
pri_chan->offer_msg.offer.sub_channel_index));
|
||||
hn_channel_attach(sc, pri_chan);
|
||||
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
ifp->if_ioctl = hn_ioctl;
|
||||
@ -578,6 +579,26 @@ netvsc_attach(device_t dev)
|
||||
device_printf(dev, "%d TX ring, %d RX ring\n",
|
||||
sc->hn_tx_ring_inuse, sc->hn_rx_ring_inuse);
|
||||
|
||||
if (sc->net_dev->num_channel > 1) {
|
||||
struct hv_vmbus_channel **subchan;
|
||||
int subchan_cnt = sc->net_dev->num_channel - 1;
|
||||
int i;
|
||||
|
||||
/* Wait for sub-channels setup to complete. */
|
||||
subchan = vmbus_get_subchan(pri_chan, subchan_cnt);
|
||||
|
||||
/* Attach the sub-channels. */
|
||||
for (i = 0; i < subchan_cnt; ++i) {
|
||||
/* NOTE: Calling order is critical. */
|
||||
hn_subchan_attach(sc, subchan[i]);
|
||||
hv_nv_subchan_attach(subchan[i]);
|
||||
}
|
||||
|
||||
/* Release the sub-channels */
|
||||
vmbus_rel_subchan(subchan, subchan_cnt);
|
||||
device_printf(dev, "%d sub-channels setup done\n", subchan_cnt);
|
||||
}
|
||||
|
||||
#if __FreeBSD_version >= 1100099
|
||||
if (sc->hn_rx_ring_inuse > 1) {
|
||||
/*
|
||||
@ -2910,8 +2931,8 @@ hn_channel_attach(struct hn_softc *sc, struct hv_vmbus_channel *chan)
|
||||
vmbus_channel_cpu_set(chan, (sc->hn_cpu + idx) % mp_ncpus);
|
||||
}
|
||||
|
||||
void
|
||||
netvsc_subchan_callback(struct hn_softc *sc, struct hv_vmbus_channel *chan)
|
||||
static void
|
||||
hn_subchan_attach(struct hn_softc *sc, struct hv_vmbus_channel *chan)
|
||||
{
|
||||
|
||||
KASSERT(!HV_VMBUS_CHAN_ISPRIMARY(chan),
|
||||
|
@ -1068,8 +1068,6 @@ struct hv_vmbus_channel;
|
||||
int netvsc_recv(struct hv_vmbus_channel *chan,
|
||||
netvsc_packet *packet, rndis_tcp_ip_csum_info *csum_info);
|
||||
void netvsc_channel_rollup(struct hv_vmbus_channel *chan);
|
||||
void netvsc_subchan_callback(struct hn_softc *sc,
|
||||
struct hv_vmbus_channel *chan);
|
||||
|
||||
void* hv_set_rppi_data(rndis_msg *rndis_mesg,
|
||||
uint32_t rppi_size,
|
||||
|
@ -134,7 +134,6 @@ struct storvsc_softc {
|
||||
uint32_t hs_num_out_reqs;
|
||||
boolean_t hs_destroy;
|
||||
boolean_t hs_drain_notify;
|
||||
boolean_t hs_open_multi_channel;
|
||||
struct sema hs_drain_sema;
|
||||
struct hv_storvsc_request hs_init_req;
|
||||
struct hv_storvsc_request hs_reset_req;
|
||||
@ -347,29 +346,19 @@ get_stor_device(struct hv_device *device,
|
||||
return sc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback handler, will be invoked when receive mutil-channel offer
|
||||
*
|
||||
* @param context new multi-channel
|
||||
*/
|
||||
static void
|
||||
storvsc_handle_sc_creation(void *context)
|
||||
storvsc_subchan_attach(struct hv_vmbus_channel *new_channel)
|
||||
{
|
||||
hv_vmbus_channel *new_channel;
|
||||
struct hv_device *device;
|
||||
struct storvsc_softc *sc;
|
||||
struct vmstor_chan_props props;
|
||||
int ret = 0;
|
||||
|
||||
new_channel = (hv_vmbus_channel *)context;
|
||||
device = new_channel->device;
|
||||
sc = get_stor_device(device, TRUE);
|
||||
if (sc == NULL)
|
||||
return;
|
||||
|
||||
if (FALSE == sc->hs_open_multi_channel)
|
||||
return;
|
||||
|
||||
memset(&props, 0, sizeof(props));
|
||||
|
||||
ret = hv_vmbus_channel_open(new_channel,
|
||||
@ -392,11 +381,12 @@ storvsc_handle_sc_creation(void *context)
|
||||
static void
|
||||
storvsc_send_multichannel_request(struct hv_device *dev, int max_chans)
|
||||
{
|
||||
struct hv_vmbus_channel **subchan;
|
||||
struct storvsc_softc *sc;
|
||||
struct hv_storvsc_request *request;
|
||||
struct vstor_packet *vstor_packet;
|
||||
int request_channels_cnt = 0;
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
/* get multichannels count that need to create */
|
||||
request_channels_cnt = MIN(max_chans, mp_ncpus);
|
||||
@ -410,9 +400,6 @@ storvsc_send_multichannel_request(struct hv_device *dev, int max_chans)
|
||||
|
||||
request = &sc->hs_init_req;
|
||||
|
||||
/* Establish a handler for multi-channel */
|
||||
dev->channel->sc_creation_callback = storvsc_handle_sc_creation;
|
||||
|
||||
/* request the host to create multi-channel */
|
||||
memset(request, 0, sizeof(struct hv_storvsc_request));
|
||||
|
||||
@ -448,7 +435,15 @@ storvsc_send_multichannel_request(struct hv_device *dev, int max_chans)
|
||||
return;
|
||||
}
|
||||
|
||||
sc->hs_open_multi_channel = TRUE;
|
||||
/* Wait for sub-channels setup to complete. */
|
||||
subchan = vmbus_get_subchan(dev->channel, request_channels_cnt);
|
||||
|
||||
/* Attach the sub-channels. */
|
||||
for (i = 0; i < request_channels_cnt; ++i)
|
||||
storvsc_subchan_attach(subchan[i]);
|
||||
|
||||
/* Release the sub-channels. */
|
||||
vmbus_rel_subchan(subchan, request_channels_cnt);
|
||||
|
||||
if (bootverbose)
|
||||
printf("Storvsc create multi-channel success!\n");
|
||||
@ -1067,7 +1062,6 @@ storvsc_attach(device_t dev)
|
||||
|
||||
sc->hs_destroy = FALSE;
|
||||
sc->hs_drain_notify = FALSE;
|
||||
sc->hs_open_multi_channel = FALSE;
|
||||
sema_init(&sc->hs_drain_sema, 0, "Store Drain Sema");
|
||||
|
||||
ret = hv_storvsc_connect_vsp(hv_dev);
|
||||
|
@ -618,7 +618,6 @@ hv_vmbus_channel_close_internal(hv_vmbus_channel *channel)
|
||||
hv_vmbus_channel_msg_info* info;
|
||||
|
||||
channel->state = HV_CHANNEL_OPEN_STATE;
|
||||
channel->sc_creation_callback = NULL;
|
||||
|
||||
/*
|
||||
* set rxq to NULL to avoid more requests be scheduled
|
||||
|
@ -177,13 +177,10 @@ hv_vmbus_free_vmbus_channel(hv_vmbus_channel* channel)
|
||||
static void
|
||||
vmbus_channel_process_offer(hv_vmbus_channel *new_channel)
|
||||
{
|
||||
boolean_t f_new;
|
||||
hv_vmbus_channel* channel;
|
||||
int ret;
|
||||
uint32_t relid;
|
||||
|
||||
f_new = TRUE;
|
||||
channel = NULL;
|
||||
relid = new_channel->offer_msg.child_rel_id;
|
||||
/*
|
||||
* Make sure this is a new offer
|
||||
@ -192,31 +189,24 @@ vmbus_channel_process_offer(hv_vmbus_channel *new_channel)
|
||||
hv_vmbus_g_connection.channels[relid] = new_channel;
|
||||
|
||||
TAILQ_FOREACH(channel, &hv_vmbus_g_connection.channel_anchor,
|
||||
list_entry)
|
||||
{
|
||||
list_entry) {
|
||||
if (memcmp(&channel->offer_msg.offer.interface_type,
|
||||
&new_channel->offer_msg.offer.interface_type,
|
||||
sizeof(hv_guid)) == 0 &&
|
||||
memcmp(&channel->offer_msg.offer.interface_instance,
|
||||
&new_channel->offer_msg.offer.interface_instance,
|
||||
sizeof(hv_guid)) == 0) {
|
||||
f_new = FALSE;
|
||||
sizeof(hv_guid)) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (f_new) {
|
||||
/* Insert at tail */
|
||||
TAILQ_INSERT_TAIL(
|
||||
&hv_vmbus_g_connection.channel_anchor,
|
||||
new_channel,
|
||||
list_entry);
|
||||
if (channel == NULL) {
|
||||
/* Install the new primary channel */
|
||||
TAILQ_INSERT_TAIL(&hv_vmbus_g_connection.channel_anchor,
|
||||
new_channel, list_entry);
|
||||
}
|
||||
mtx_unlock(&hv_vmbus_g_connection.channel_lock);
|
||||
|
||||
/*XXX add new channel to percpu_list */
|
||||
|
||||
if (!f_new) {
|
||||
if (channel != NULL) {
|
||||
/*
|
||||
* Check if this is a sub channel.
|
||||
*/
|
||||
@ -227,10 +217,8 @@ vmbus_channel_process_offer(hv_vmbus_channel *new_channel)
|
||||
new_channel->primary_channel = channel;
|
||||
new_channel->device = channel->device;
|
||||
mtx_lock(&channel->sc_lock);
|
||||
TAILQ_INSERT_TAIL(
|
||||
&channel->sc_list_anchor,
|
||||
new_channel,
|
||||
sc_list_entry);
|
||||
TAILQ_INSERT_TAIL(&channel->sc_list_anchor,
|
||||
new_channel, sc_list_entry);
|
||||
mtx_unlock(&channel->sc_lock);
|
||||
|
||||
if (bootverbose) {
|
||||
@ -251,17 +239,25 @@ vmbus_channel_process_offer(hv_vmbus_channel *new_channel)
|
||||
"its primary channel is <%p>.\n",
|
||||
new_channel, new_channel->primary_channel);
|
||||
|
||||
/*XXX add it to percpu_list */
|
||||
|
||||
new_channel->state = HV_CHANNEL_OPEN_STATE;
|
||||
if (channel->sc_creation_callback != NULL) {
|
||||
channel->sc_creation_callback(new_channel);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bump up sub-channel count and notify anyone that is
|
||||
* interested in this sub-channel, after this sub-channel
|
||||
* is setup.
|
||||
*/
|
||||
mtx_lock(&channel->sc_lock);
|
||||
channel->subchan_cnt++;
|
||||
mtx_unlock(&channel->sc_lock);
|
||||
wakeup(channel);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
hv_vmbus_free_vmbus_channel(new_channel);
|
||||
return;
|
||||
printf("VMBUS: duplicated primary channel%u\n",
|
||||
new_channel->offer_msg.child_rel_id);
|
||||
hv_vmbus_free_vmbus_channel(new_channel);
|
||||
return;
|
||||
}
|
||||
|
||||
new_channel->state = HV_CHANNEL_OPEN_STATE;
|
||||
@ -283,10 +279,8 @@ vmbus_channel_process_offer(hv_vmbus_channel *new_channel)
|
||||
ret = hv_vmbus_child_device_register(new_channel->device);
|
||||
if (ret != 0) {
|
||||
mtx_lock(&hv_vmbus_g_connection.channel_lock);
|
||||
TAILQ_REMOVE(
|
||||
&hv_vmbus_g_connection.channel_anchor,
|
||||
new_channel,
|
||||
list_entry);
|
||||
TAILQ_REMOVE(&hv_vmbus_g_connection.channel_anchor,
|
||||
new_channel, list_entry);
|
||||
mtx_unlock(&hv_vmbus_g_connection.channel_lock);
|
||||
hv_vmbus_free_vmbus_channel(new_channel);
|
||||
}
|
||||
@ -793,3 +787,41 @@ vmbus_scan(void)
|
||||
mtx_sleep(&vmbus_devcnt, &vmbus_chwait_lock, 0, "waitdev", 0);
|
||||
mtx_unlock(&vmbus_chwait_lock);
|
||||
}
|
||||
|
||||
struct hv_vmbus_channel **
|
||||
vmbus_get_subchan(struct hv_vmbus_channel *pri_chan, int subchan_cnt)
|
||||
{
|
||||
struct hv_vmbus_channel **ret, *chan;
|
||||
int i;
|
||||
|
||||
ret = malloc(subchan_cnt * sizeof(struct hv_vmbus_channel *), M_TEMP,
|
||||
M_WAITOK);
|
||||
|
||||
mtx_lock(&pri_chan->sc_lock);
|
||||
|
||||
while (pri_chan->subchan_cnt < subchan_cnt)
|
||||
mtx_sleep(pri_chan, &pri_chan->sc_lock, 0, "subch", 0);
|
||||
|
||||
i = 0;
|
||||
TAILQ_FOREACH(chan, &pri_chan->sc_list_anchor, sc_list_entry) {
|
||||
/* TODO: refcnt chan */
|
||||
ret[i] = chan;
|
||||
|
||||
++i;
|
||||
if (i == subchan_cnt)
|
||||
break;
|
||||
}
|
||||
KASSERT(i == subchan_cnt, ("invalid subchan count %d, should be %d",
|
||||
pri_chan->subchan_cnt, subchan_cnt));
|
||||
|
||||
mtx_unlock(&pri_chan->sc_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
vmbus_rel_subchan(struct hv_vmbus_channel **subchan, int subchan_cnt __unused)
|
||||
{
|
||||
|
||||
free(subchan, M_TEMP);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user