Author: sephe
Date: Mon Oct 17 01:59:42 2016
New Revision: 307449
URL: https://svnweb.freebsd.org/changeset/base/307449

Log:
  MFC 302808-302815
  
  302808
      hyperv/vmbus: Alloc/Free monitor param in vmbus channel alloc/free.
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D7101
  
  302809
      hyperv/vmbus: Move device register and channel free to the caller.
  
      This paves the way for more cleanup/disentangle.
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D7102
  
  302810
      hyperv/vmbus: Move new channel scan notification to device register
  
      And nuke now unnecessary function indirection.
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D7103
  
  302811
      hyperv/vmbus: Cleanup vmbus_chan_msgproc_choffer
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D7104
  
  302812
      hyperv/vmbus: Nuke the channel open state.
  
      Channel is either opened or not-opened.
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D7105
  
  302813
      hyperv/vmbus: Cleanup vmbus_chan_add()
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D7106
  
  302814
      hyperv/vmbus: Use sub-channel index to detect primary channel
  
      In case that VMBUS_CHAN_ISPRIMARY is needed in the early place of
      channel setup.
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D7108
  
  302815
      hyperv/vmbus: Only add primary channels to vmbus channel list
  
      - Make the vmbus_chan_add more straightforward.
      - Partially fix the hv_vmbus_release_unattached_channels().
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D7109

Modified:
  stable/11/sys/dev/hyperv/include/hyperv.h
  stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c
  stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
  stable/11/sys/dev/hyperv/vmbus/hv_channel.c
  stable/11/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
  stable/11/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
  stable/11/sys/dev/hyperv/vmbus/vmbus.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/hyperv/include/hyperv.h
==============================================================================
--- stable/11/sys/dev/hyperv/include/hyperv.h   Mon Oct 17 01:47:49 2016        
(r307448)
+++ stable/11/sys/dev/hyperv/include/hyperv.h   Mon Oct 17 01:59:42 2016        
(r307449)
@@ -244,18 +244,9 @@ typedef struct {
 
 typedef void (*hv_vmbus_pfn_channel_callback)(void *context);
 
-typedef enum {
-       HV_CHANNEL_OFFER_STATE,
-       HV_CHANNEL_OPENING_STATE,
-       HV_CHANNEL_OPEN_STATE,
-       HV_CHANNEL_OPENED_STATE,
-       HV_CHANNEL_CLOSING_NONDESTRUCTIVE_STATE,
-} hv_vmbus_channel_state;
-
 typedef struct hv_vmbus_channel {
        device_t                        ch_dev;
        struct vmbus_softc              *vmbus_sc;
-       hv_vmbus_channel_state          state;
        uint32_t                        ch_flags;       /* VMBUS_CHAN_FLAG_ */
        uint32_t                        ch_id;          /* channel id */
 
@@ -337,14 +328,15 @@ typedef struct hv_vmbus_channel {
        struct task                     ch_detach_task;
        TAILQ_ENTRY(hv_vmbus_channel)   ch_link;
        uint32_t                        ch_subidx;      /* subchan index */
-
+       volatile uint32_t               ch_stflags;     /* atomic-op */
+                                                       /* VMBUS_CHAN_ST_ */
        struct hyperv_guid              ch_guid_type;
        struct hyperv_guid              ch_guid_inst;
 
        struct sysctl_ctx_list          ch_sysctl_ctx;
 } hv_vmbus_channel;
 
-#define HV_VMBUS_CHAN_ISPRIMARY(chan)  ((chan)->primary_channel == NULL)
+#define VMBUS_CHAN_ISPRIMARY(chan)     ((chan)->ch_subidx == 0)
 
 #define VMBUS_CHAN_FLAG_HASMNF         0x0001
 /*
@@ -357,6 +349,9 @@ typedef struct hv_vmbus_channel {
  */
 #define VMBUS_CHAN_FLAG_BATCHREAD      0x0002
 
+#define VMBUS_CHAN_ST_OPENED_SHIFT     0
+#define VMBUS_CHAN_ST_OPENED           (1 << VMBUS_CHAN_ST_OPENED_SHIFT)
+
 static inline void
 hv_set_channel_read_state(hv_vmbus_channel* channel, boolean_t on)
 {

Modified: stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c        Mon Oct 17 01:47:49 
2016        (r307448)
+++ stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c        Mon Oct 17 01:59:42 
2016        (r307449)
@@ -719,11 +719,6 @@ hv_nv_on_device_remove(struct hn_softc *
 
        /* Now, we can close the channel safely */
 
-       if (!destroy_channel) {
-               sc->hn_prichan->state =
-                   HV_CHANNEL_CLOSING_NONDESTRUCTIVE_STATE;
-       }
-
        free(sc->hn_prichan->hv_chan_rdbuf, M_NETVSC);
        hv_vmbus_channel_close(sc->hn_prichan);
 

Modified: stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c     Mon Oct 17 
01:47:49 2016        (r307448)
+++ stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c     Mon Oct 17 
01:59:42 2016        (r307449)
@@ -2957,7 +2957,7 @@ static void
 hn_subchan_attach(struct hn_softc *sc, struct hv_vmbus_channel *chan)
 {
 
-       KASSERT(!HV_VMBUS_CHAN_ISPRIMARY(chan),
+       KASSERT(!VMBUS_CHAN_ISPRIMARY(chan),
            ("subchannel callback on primary channel"));
        KASSERT(chan->ch_subidx > 0,
            ("invalid channel subidx %u",

Modified: stable/11/sys/dev/hyperv/vmbus/hv_channel.c
==============================================================================
--- stable/11/sys/dev/hyperv/vmbus/hv_channel.c Mon Oct 17 01:47:49 2016        
(r307448)
+++ stable/11/sys/dev/hyperv/vmbus/hv_channel.c Mon Oct 17 01:59:42 2016        
(r307449)
@@ -191,17 +191,9 @@ hv_vmbus_channel_open(
                return EINVAL;
        }
 
-       mtx_lock(&new_channel->sc_lock);
-       if (new_channel->state == HV_CHANNEL_OPEN_STATE) {
-           new_channel->state = HV_CHANNEL_OPENING_STATE;
-       } else {
-           mtx_unlock(&new_channel->sc_lock);
-           if(bootverbose)
-               printf("VMBUS: Trying to open channel <%p> which in "
-                   "%d state.\n", new_channel, new_channel->state);
-           return (EINVAL);
-       }
-       mtx_unlock(&new_channel->sc_lock);
+       if (atomic_testandset_int(&new_channel->ch_stflags,
+           VMBUS_CHAN_ST_OPENED_SHIFT))
+               panic("double-open chan%u", new_channel->ch_id);
 
        new_channel->on_channel_callback = pfn_on_channel_callback;
        new_channel->channel_callback_context = context;
@@ -223,8 +215,10 @@ hv_vmbus_channel_open(
            M_DEVBUF, M_ZERO, 0UL, BUS_SPACE_MAXADDR, PAGE_SIZE, 0);
        KASSERT(out != NULL,
            ("Error VMBUS: contigmalloc failed to allocate Ring Buffer!"));
-       if (out == NULL)
-               return (ENOMEM);
+       if (out == NULL) {
+               ret = ENOMEM;
+               goto failed;
+       }
 
        in = ((uint8_t *) out + send_ring_buffer_size);
 
@@ -265,7 +259,8 @@ hv_vmbus_channel_open(
                device_printf(sc->vmbus_dev,
                    "can not get msg hypercall for chopen(chan%u)\n",
                    new_channel->ch_id);
-               return ENXIO;
+               ret = ENXIO;
+               goto failed;
        }
 
        req = vmbus_msghc_dataptr(mh);
@@ -284,7 +279,7 @@ hv_vmbus_channel_open(
                    "chopen(chan%u) msg hypercall exec failed: %d\n",
                    new_channel->ch_id, ret);
                vmbus_msghc_put(sc, mh);
-               return ret;
+               goto failed;
        }
 
        msg = vmbus_msghc_wait_result(sc, mh);
@@ -294,17 +289,20 @@ hv_vmbus_channel_open(
        vmbus_msghc_put(sc, mh);
 
        if (status == 0) {
-               new_channel->state = HV_CHANNEL_OPENED_STATE;
                if (bootverbose) {
                        device_printf(sc->vmbus_dev, "chan%u opened\n",
                            new_channel->ch_id);
                }
-       } else {
-               device_printf(sc->vmbus_dev, "failed to open chan%u\n",
-                   new_channel->ch_id);
-               ret = ENXIO;
+               return 0;
        }
-       return (ret);
+
+       device_printf(sc->vmbus_dev, "failed to open chan%u\n",
+           new_channel->ch_id);
+       ret = ENXIO;
+
+failed:
+       atomic_clear_int(&new_channel->ch_stflags, VMBUS_CHAN_ST_OPENED);
+       return ret;
 }
 
 /**
@@ -487,7 +485,9 @@ hv_vmbus_channel_close_internal(hv_vmbus
        struct taskqueue *rxq = channel->rxq;
        int error;
 
-       channel->state = HV_CHANNEL_OPEN_STATE;
+       /* TODO: stringent check */
+       atomic_clear_int(&channel->ch_stflags, VMBUS_CHAN_ST_OPENED);
+
        sysctl_ctx_free(&channel->ch_sysctl_ctx);
 
        /*
@@ -563,7 +563,7 @@ hv_vmbus_channel_close(hv_vmbus_channel 
         */
        TAILQ_FOREACH(sub_channel, &channel->sc_list_anchor,
            sc_list_entry) {
-               if (sub_channel->state != HV_CHANNEL_OPENED_STATE)
+               if ((sub_channel->ch_stflags & VMBUS_CHAN_ST_OPENED) == 0)
                        continue;
                hv_vmbus_channel_close_internal(sub_channel);
        }

Modified: stable/11/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
==============================================================================
--- stable/11/sys/dev/hyperv/vmbus/hv_channel_mgmt.c    Mon Oct 17 01:47:49 
2016        (r307448)
+++ stable/11/sys/dev/hyperv/vmbus/hv_channel_mgmt.c    Mon Oct 17 01:59:42 
2016        (r307449)
@@ -40,15 +40,12 @@
 typedef void   (*vmbus_chanmsg_proc_t)
                (struct vmbus_softc *, const struct vmbus_message *);
 
-static struct hv_vmbus_channel *hv_vmbus_allocate_channel(struct vmbus_softc 
*);
-static void    vmbus_channel_on_offer_internal(struct vmbus_softc *,
-                   const struct vmbus_chanmsg_choffer *);
 static void    vmbus_chan_detach_task(void *, int);
 
-static void    vmbus_channel_on_offer(struct vmbus_softc *,
-                   const struct vmbus_message *);
 static void    vmbus_channel_on_offers_delivered(struct vmbus_softc *,
                    const struct vmbus_message *);
+static void    vmbus_chan_msgproc_choffer(struct vmbus_softc *,
+                   const struct vmbus_message *);
 static void    vmbus_chan_msgproc_chrescind(struct vmbus_softc *,
                    const struct vmbus_message *);
 
@@ -63,7 +60,7 @@ static void   vmbus_chan_msgproc_chrescind
 
 static const vmbus_chanmsg_proc_t
 vmbus_chanmsg_process[VMBUS_CHANMSG_TYPE_MAX] = {
-       VMBUS_CHANMSG_PROC(CHOFFER,     vmbus_channel_on_offer),
+       VMBUS_CHANMSG_PROC(CHOFFER,     vmbus_chan_msgproc_choffer),
        VMBUS_CHANMSG_PROC(CHRESCIND,   vmbus_chan_msgproc_chrescind),
        VMBUS_CHANMSG_PROC(CHOFFER_DONE,vmbus_channel_on_offers_delivered),
 
@@ -76,146 +73,125 @@ vmbus_chanmsg_process[VMBUS_CHANMSG_TYPE
 #undef VMBUS_CHANMSG_PROC_WAKEUP
 #undef VMBUS_CHANMSG_PROC
 
-/**
- * @brief Allocate and initialize a vmbus channel object
- */
 static struct hv_vmbus_channel *
-hv_vmbus_allocate_channel(struct vmbus_softc *sc)
+vmbus_chan_alloc(struct vmbus_softc *sc)
 {
-       struct hv_vmbus_channel *channel;
+       struct hv_vmbus_channel *chan;
 
-       channel = malloc(sizeof(*channel), M_DEVBUF, M_WAITOK | M_ZERO);
-       channel->vmbus_sc = sc;
+       chan = malloc(sizeof(*chan), M_DEVBUF, M_WAITOK | M_ZERO);
 
-       mtx_init(&channel->sc_lock, "vmbus multi channel", NULL, MTX_DEF);
-       TAILQ_INIT(&channel->sc_list_anchor);
-       TASK_INIT(&channel->ch_detach_task, 0, vmbus_chan_detach_task, channel);
+       chan->ch_monprm = hyperv_dmamem_alloc(bus_get_dma_tag(sc->vmbus_dev),
+           HYPERCALL_PARAM_ALIGN, 0, sizeof(struct hyperv_mon_param),
+           &chan->ch_monprm_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
+       if (chan->ch_monprm == NULL) {
+               device_printf(sc->vmbus_dev, "monprm alloc failed\n");
+               free(chan, M_DEVBUF);
+               return NULL;
+       }
 
-       return (channel);
+       chan->vmbus_sc = sc;
+       mtx_init(&chan->sc_lock, "vmbus multi channel", NULL, MTX_DEF);
+       TAILQ_INIT(&chan->sc_list_anchor);
+       TASK_INIT(&chan->ch_detach_task, 0, vmbus_chan_detach_task, chan);
+
+       return chan;
 }
 
-/**
- * @brief Release the resources used by the vmbus channel object
- */
-void
-hv_vmbus_free_vmbus_channel(hv_vmbus_channel* channel)
+static void
+vmbus_chan_free(struct hv_vmbus_channel *chan)
 {
-       mtx_destroy(&channel->sc_lock);
-       free(channel, M_DEVBUF);
+       /* TODO: assert sub-channel list is empty */
+       /* TODO: asset no longer on the primary channel's sub-channel list */
+       /* TODO: asset no longer on the vmbus channel list */
+       hyperv_dmamem_free(&chan->ch_monprm_dma, chan->ch_monprm);
+       mtx_destroy(&chan->sc_lock);
+       free(chan, M_DEVBUF);
 }
 
-/**
- * @brief Process the offer by creating a channel/device
- * associated with this offer
- */
-static void
-vmbus_channel_process_offer(hv_vmbus_channel *new_channel)
+static int
+vmbus_chan_add(struct hv_vmbus_channel *newchan)
 {
-       struct vmbus_softc *sc = new_channel->vmbus_sc;
-       hv_vmbus_channel*       channel;
+       struct vmbus_softc *sc = newchan->vmbus_sc;
+       struct hv_vmbus_channel *prichan;
 
-       /*
-        * Make sure this is a new offer
-        */
-       mtx_lock(&sc->vmbus_chlist_lock);
-       if (new_channel->ch_id == 0) {
+       if (newchan->ch_id == 0) {
                /*
-                * XXX channel0 will not be processed; skip it.
+                * XXX
+                * Chan0 will neither be processed nor should be offered;
+                * skip it.
                 */
-               printf("VMBUS: got channel0 offer\n");
-       } else {
-               sc->vmbus_chmap[new_channel->ch_id] = new_channel;
+               device_printf(sc->vmbus_dev, "got chan0 offer, discard\n");
+               return EINVAL;
+       } else if (newchan->ch_id >= VMBUS_CHAN_MAX) {
+               device_printf(sc->vmbus_dev, "invalid chan%u offer\n",
+                   newchan->ch_id);
+               return EINVAL;
        }
+       sc->vmbus_chmap[newchan->ch_id] = newchan;
 
-       TAILQ_FOREACH(channel, &sc->vmbus_chlist, ch_link) {
-               if (memcmp(&channel->ch_guid_type, &new_channel->ch_guid_type,
+       if (bootverbose) {
+               device_printf(sc->vmbus_dev, "chan%u subidx%u offer\n",
+                   newchan->ch_id, newchan->ch_subidx);
+       }
+
+       mtx_lock(&sc->vmbus_chlist_lock);
+       TAILQ_FOREACH(prichan, &sc->vmbus_chlist, ch_link) {
+               if (memcmp(&prichan->ch_guid_type, &newchan->ch_guid_type,
                    sizeof(struct hyperv_guid)) == 0 &&
-                   memcmp(&channel->ch_guid_inst, &new_channel->ch_guid_inst,
+                   memcmp(&prichan->ch_guid_inst, &newchan->ch_guid_inst,
                    sizeof(struct hyperv_guid)) == 0)
                        break;
        }
-
-       if (channel == NULL) {
-               /* Install the new primary channel */
-               TAILQ_INSERT_TAIL(&sc->vmbus_chlist, new_channel, ch_link);
-       }
-       mtx_unlock(&sc->vmbus_chlist_lock);
-
-       if (bootverbose) {
-               char logstr[64];
-
-               logstr[0] = '\0';
-               if (channel != NULL) {
-                       snprintf(logstr, sizeof(logstr), ", primary chan%u",
-                           channel->ch_id);
+       if (VMBUS_CHAN_ISPRIMARY(newchan)) {
+               if (prichan == NULL) {
+                       /* Install the new primary channel */
+                       TAILQ_INSERT_TAIL(&sc->vmbus_chlist, newchan, ch_link);
+                       mtx_unlock(&sc->vmbus_chlist_lock);
+                       return 0;
+               } else {
+                       mtx_unlock(&sc->vmbus_chlist_lock);
+                       device_printf(sc->vmbus_dev, "duplicated primary "
+                           "chan%u\n", newchan->ch_id);
+                       return EINVAL;
                }
-               device_printf(sc->vmbus_dev, "chan%u subchanid%u offer%s\n",
-                   new_channel->ch_id,
-                   new_channel->ch_subidx, logstr);
-       }
-
-       if (channel != NULL) {
-               /*
-                * Check if this is a sub channel.
-                */
-               if (new_channel->ch_subidx != 0) {
-                       /*
-                        * It is a sub channel offer, process it.
-                        */
-                       new_channel->primary_channel = channel;
-                       new_channel->ch_dev = channel->ch_dev;
-                       mtx_lock(&channel->sc_lock);
-                       TAILQ_INSERT_TAIL(&channel->sc_list_anchor,
-                           new_channel, sc_list_entry);
-                       mtx_unlock(&channel->sc_lock);
-
-                       /*
-                        * Insert the new channel to the end of the global
-                        * channel list.
-                        *
-                        * 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);
+       } else { /* Sub-channel */
+               if (prichan == NULL) {
                        mtx_unlock(&sc->vmbus_chlist_lock);
-
-                       new_channel->state = HV_CHANNEL_OPEN_STATE;
-
-                       /*
-                        * 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;
+                       device_printf(sc->vmbus_dev, "no primary chan for "
+                           "chan%u\n", newchan->ch_id);
+                       return EINVAL;
                }
-
-               printf("VMBUS: duplicated primary channel%u\n",
-                   new_channel->ch_id);
-               hv_vmbus_free_vmbus_channel(new_channel);
-               return;
+               /*
+                * Found the primary channel for this sub-channel and
+                * move on.
+                *
+                * XXX refcnt prichan
+                */
        }
+       mtx_unlock(&sc->vmbus_chlist_lock);
+
+       /*
+        * This is a sub-channel; link it with the primary channel.
+        */
+       KASSERT(!VMBUS_CHAN_ISPRIMARY(newchan),
+           ("new channel is not sub-channel"));
+       KASSERT(prichan != NULL, ("no primary channel"));
 
-       new_channel->state = HV_CHANNEL_OPEN_STATE;
+       newchan->primary_channel = prichan;
+       newchan->ch_dev = prichan->ch_dev;
 
+       mtx_lock(&prichan->sc_lock);
+       TAILQ_INSERT_TAIL(&prichan->sc_list_anchor, newchan, sc_list_entry);
        /*
-        * Add the new device to the bus. This will kick off device-driver
-        * binding which eventually invokes the device driver's AddDevice()
-        * method.
-        *
-        * NOTE:
-        * Error is ignored here; don't have much to do if error really
-        * happens.
+        * Bump up sub-channel count and notify anyone that is
+        * interested in this sub-channel, after this sub-channel
+        * is setup.
         */
-       hv_vmbus_child_device_register(new_channel);
+       prichan->subchan_cnt++;
+       mtx_unlock(&prichan->sc_lock);
+       wakeup(prichan);
+
+       return 0;
 }
 
 void
@@ -250,7 +226,7 @@ vmbus_channel_cpu_rr(struct hv_vmbus_cha
 }
 
 static void
-vmbus_channel_select_defcpu(struct hv_vmbus_channel *chan)
+vmbus_chan_cpu_default(struct hv_vmbus_channel *chan)
 {
        /*
         * By default, pin the channel to cpu0.  Devices having
@@ -260,69 +236,68 @@ vmbus_channel_select_defcpu(struct hv_vm
        vmbus_channel_cpu_set(chan, 0);
 }
 
-/**
- * @brief Handler for channel offers from Hyper-V/Azure
- *
- * Handler for channel offers from vmbus in parent partition.
- */
 static void
-vmbus_channel_on_offer(struct vmbus_softc *sc, const struct vmbus_message *msg)
+vmbus_chan_msgproc_choffer(struct vmbus_softc *sc,
+    const struct vmbus_message *msg)
 {
-       /* New channel is offered by vmbus */
-       vmbus_scan_newchan(sc);
+       const struct vmbus_chanmsg_choffer *offer;
+       struct hv_vmbus_channel *chan;
+       int error;
 
-       vmbus_channel_on_offer_internal(sc,
-           (const struct vmbus_chanmsg_choffer *)msg->msg_data);
-}
+       offer = (const struct vmbus_chanmsg_choffer *)msg->msg_data;
 
-static void
-vmbus_channel_on_offer_internal(struct vmbus_softc *sc,
-    const struct vmbus_chanmsg_choffer *offer)
-{
-       hv_vmbus_channel* new_channel;
+       chan = vmbus_chan_alloc(sc);
+       if (chan == NULL) {
+               device_printf(sc->vmbus_dev, "allocate chan%u failed\n",
+                   offer->chm_chanid);
+               return;
+       }
 
-       /*
-        * Allocate the channel object and save this offer
-        */
-       new_channel = hv_vmbus_allocate_channel(sc);
-       new_channel->ch_id = offer->chm_chanid;
-       new_channel->ch_subidx = offer->chm_subidx;
-       new_channel->ch_guid_type = offer->chm_chtype;
-       new_channel->ch_guid_inst = offer->chm_chinst;
+       chan->ch_id = offer->chm_chanid;
+       chan->ch_subidx = offer->chm_subidx;
+       chan->ch_guid_type = offer->chm_chtype;
+       chan->ch_guid_inst = offer->chm_chinst;
 
        /* Batch reading is on by default */
-       new_channel->ch_flags |= VMBUS_CHAN_FLAG_BATCHREAD;
-       if (offer->chm_flags1 & VMBUS_CHOFFER_FLAG1_HASMNF)
-               new_channel->ch_flags |= VMBUS_CHAN_FLAG_HASMNF;
+       chan->ch_flags |= VMBUS_CHAN_FLAG_BATCHREAD;
 
-       new_channel->ch_monprm = hyperv_dmamem_alloc(
-           bus_get_dma_tag(sc->vmbus_dev),
-           HYPERCALL_PARAM_ALIGN, 0, sizeof(struct hyperv_mon_param),
-           &new_channel->ch_monprm_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
-       if (new_channel->ch_monprm == NULL) {
-               device_printf(sc->vmbus_dev, "monprm alloc failed\n");
-               /* XXX */
-               mtx_destroy(&new_channel->sc_lock);
-               free(new_channel, M_DEVBUF);
-               return;
-       }
-       new_channel->ch_monprm->mp_connid = VMBUS_CONNID_EVENT;
+       chan->ch_monprm->mp_connid = VMBUS_CONNID_EVENT;
        if (sc->vmbus_version != VMBUS_VERSION_WS2008)
-               new_channel->ch_monprm->mp_connid = offer->chm_connid;
+               chan->ch_monprm->mp_connid = offer->chm_connid;
 
-       if (new_channel->ch_flags & VMBUS_CHAN_FLAG_HASMNF) {
-               new_channel->ch_montrig_idx =
-                   offer->chm_montrig / VMBUS_MONTRIG_LEN;
-               if (new_channel->ch_montrig_idx >= VMBUS_MONTRIGS_MAX)
+       if (offer->chm_flags1 & VMBUS_CHOFFER_FLAG1_HASMNF) {
+               /*
+                * Setup MNF stuffs.
+                */
+               chan->ch_flags |= VMBUS_CHAN_FLAG_HASMNF;
+               chan->ch_montrig_idx = offer->chm_montrig / VMBUS_MONTRIG_LEN;
+               if (chan->ch_montrig_idx >= VMBUS_MONTRIGS_MAX)
                        panic("invalid monitor trigger %u", offer->chm_montrig);
-               new_channel->ch_montrig_mask =
+               chan->ch_montrig_mask =
                    1 << (offer->chm_montrig % VMBUS_MONTRIG_LEN);
        }
 
        /* Select default cpu for this channel. */
-       vmbus_channel_select_defcpu(new_channel);
+       vmbus_chan_cpu_default(chan);
 
-       vmbus_channel_process_offer(new_channel);
+       error = vmbus_chan_add(chan);
+       if (error) {
+               device_printf(sc->vmbus_dev, "add chan%u failed: %d\n",
+                   chan->ch_id, error);
+               vmbus_chan_free(chan);
+               return;
+       }
+
+       if (VMBUS_CHAN_ISPRIMARY(chan)) {
+               /*
+                * Add device for this primary channel.
+                *
+                * NOTE:
+                * Error is ignored here; don't have much to do if error
+                * really happens.
+                */
+               hv_vmbus_child_device_register(chan);
+       }
 }
 
 /*
@@ -360,7 +335,7 @@ vmbus_chan_detach_task(void *xchan, int 
 {
        struct hv_vmbus_channel *chan = xchan;
 
-       if (HV_VMBUS_CHAN_ISPRIMARY(chan)) {
+       if (VMBUS_CHAN_ISPRIMARY(chan)) {
                /* Only primary channel owns the device */
                hv_vmbus_child_device_unregister(chan);
                /* NOTE: DO NOT free primary channel for now */
@@ -398,10 +373,6 @@ vmbus_chan_detach_task(void *xchan, int 
                        }
                }
 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,
@@ -410,7 +381,7 @@ remove:
                mtx_unlock(&pri_chan->sc_lock);
                wakeup(pri_chan);
 
-               hv_vmbus_free_vmbus_channel(chan);
+               vmbus_chan_free(chan);
        }
 }
 
@@ -439,13 +410,11 @@ hv_vmbus_release_unattached_channels(str
 
        while (!TAILQ_EMPTY(&sc->vmbus_chlist)) {
            channel = TAILQ_FIRST(&sc->vmbus_chlist);
+           KASSERT(VMBUS_CHAN_ISPRIMARY(channel), ("not primary channel"));
            TAILQ_REMOVE(&sc->vmbus_chlist, channel, ch_link);
 
-           if (HV_VMBUS_CHAN_ISPRIMARY(channel)) {
-               /* Only primary channel owns the device */
-               hv_vmbus_child_device_unregister(channel);
-           }
-           hv_vmbus_free_vmbus_channel(channel);
+           hv_vmbus_child_device_unregister(channel);
+           vmbus_chan_free(channel);
        }
        bzero(sc->vmbus_chmap,
            sizeof(struct hv_vmbus_channel *) * VMBUS_CHAN_MAX);
@@ -483,7 +452,7 @@ vmbus_select_outgoing_channel(struct hv_
        cur_vcpu = VMBUS_PCPU_GET(primary->vmbus_sc, vcpuid, smp_pro_id);
        
        TAILQ_FOREACH(new_channel, &primary->sc_list_anchor, sc_list_entry) {
-               if (new_channel->state != HV_CHANNEL_OPENED_STATE){
+               if ((new_channel->ch_stflags & VMBUS_CHAN_ST_OPENED) == 0) {
                        continue;
                }
 

Modified: stable/11/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
==============================================================================
--- stable/11/sys/dev/hyperv/vmbus/hv_vmbus_priv.h      Mon Oct 17 01:47:49 
2016        (r307448)
+++ stable/11/sys/dev/hyperv/vmbus/hv_vmbus_priv.h      Mon Oct 17 01:59:42 
2016        (r307449)
@@ -55,7 +55,6 @@ typedef struct {
 
 typedef struct {
        uint32_t                rel_id;
-       hv_vmbus_channel_state  state;
        struct hyperv_guid      interface_type;
        struct hyperv_guid      interface_instance;
        uint32_t                monitor_id;
@@ -147,7 +146,6 @@ void                        hv_ring_buffer_read_begin(
 uint32_t               hv_ring_buffer_read_end(
                                hv_vmbus_ring_buffer_info       *ring_info);
 
-void                   hv_vmbus_free_vmbus_channel(hv_vmbus_channel *channel);
 void                   hv_vmbus_release_unattached_channels(
                            struct vmbus_softc *);
 

Modified: stable/11/sys/dev/hyperv/vmbus/vmbus.c
==============================================================================
--- stable/11/sys/dev/hyperv/vmbus/vmbus.c      Mon Oct 17 01:47:49 2016        
(r307448)
+++ stable/11/sys/dev/hyperv/vmbus/vmbus.c      Mon Oct 17 01:59:42 2016        
(r307449)
@@ -994,6 +994,9 @@ hv_vmbus_child_device_register(struct hv
        device_t parent = sc->vmbus_dev;
        int error = 0;
 
+       /* New channel has been offered */
+       vmbus_scan_newchan(sc);
+
        chan->ch_dev = device_add_child(parent, NULL, -1);
        if (chan->ch_dev == NULL) {
                device_printf(parent, "device_add_child for chan%u failed\n",
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to