Author: sephe
Date: Mon Dec 12 05:18:03 2016
New Revision: 309875
URL: https://svnweb.freebsd.org/changeset/base/309875

Log:
  hyperv/hn: Add polling support
  
  MFC after:    1 week
  Sponsored by: Microsoft
  Differential Revision:        https://reviews.freebsd.org/D8739

Modified:
  head/sys/dev/hyperv/netvsc/if_hn.c
  head/sys/dev/hyperv/netvsc/if_hnvar.h

Modified: head/sys/dev/hyperv/netvsc/if_hn.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/if_hn.c  Mon Dec 12 05:04:55 2016        
(r309874)
+++ head/sys/dev/hyperv/netvsc/if_hn.c  Mon Dec 12 05:18:03 2016        
(r309875)
@@ -293,6 +293,7 @@ static int                  hn_txagg_size_sysctl(SYSCTL
 static int                     hn_txagg_pkts_sysctl(SYSCTL_HANDLER_ARGS);
 static int                     hn_txagg_pktmax_sysctl(SYSCTL_HANDLER_ARGS);
 static int                     hn_txagg_align_sysctl(SYSCTL_HANDLER_ARGS);
+static int                     hn_polling_sysctl(SYSCTL_HANDLER_ARGS);
 
 static void                    hn_stop(struct hn_softc *);
 static void                    hn_init_locked(struct hn_softc *);
@@ -319,6 +320,8 @@ static void                 hn_resume_mgmt(struct hn_s
 static void                    hn_suspend_mgmt_taskfunc(void *, int);
 static void                    hn_chan_drain(struct hn_softc *,
                                    struct vmbus_channel *);
+static void                    hn_polling(struct hn_softc *, u_int);
+static void                    hn_chan_polling(struct vmbus_channel *, u_int);
 
 static void                    hn_update_link_status(struct hn_softc *);
 static void                    hn_change_network(struct hn_softc *);
@@ -1117,6 +1120,10 @@ hn_attach(device_t dev)
            hn_txagg_pkts_sysctl, "I",
            "Packet transmission aggregation packets, "
            "0 -- disable, -1 -- auto");
+       SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "polling",
+           CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, 0,
+           hn_polling_sysctl, "I",
+           "Polling frequency: [100,1000000], 0 disable polling");
 
        /*
         * Setup the ifmedia, which has been initialized earlier.
@@ -2360,6 +2367,9 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, 
                        break;
                }
 
+               /* Disable polling. */
+               hn_polling(sc, 0);
+
                /*
                 * Suspend this interface before the synthetic parts
                 * are ripped.
@@ -2405,6 +2415,13 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, 
                 */
                hn_resume(sc);
 
+               /*
+                * Re-enable polling if this interface is running and
+                * the polling is requested.
+                */
+               if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && sc->hn_pollhz > 0)
+                       hn_polling(sc, sc->hn_pollhz);
+
                HN_UNLOCK(sc);
                break;
 
@@ -2531,6 +2548,9 @@ hn_stop(struct hn_softc *sc)
        KASSERT(sc->hn_flags & HN_FLAG_SYNTH_ATTACHED,
            ("synthetic parts were not attached"));
 
+       /* Disable polling. */
+       hn_polling(sc, 0);
+
        /* Clear RUNNING bit _before_ hn_suspend_data() */
        atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_RUNNING);
        hn_suspend_data(sc);
@@ -2568,6 +2588,10 @@ hn_init_locked(struct hn_softc *sc)
 
        /* Everything is ready; unleash! */
        atomic_set_int(&ifp->if_drv_flags, IFF_DRV_RUNNING);
+
+       /* Re-enable polling if requested. */
+       if (sc->hn_pollhz > 0)
+               hn_polling(sc, sc->hn_pollhz);
 }
 
 static void
@@ -2875,6 +2899,61 @@ hn_txagg_align_sysctl(SYSCTL_HANDLER_ARG
        return (sysctl_handle_int(oidp, &align, 0, req));
 }
 
+static void
+hn_chan_polling(struct vmbus_channel *chan, u_int pollhz)
+{
+       if (pollhz == 0)
+               vmbus_chan_poll_disable(chan);
+       else
+               vmbus_chan_poll_enable(chan, pollhz);
+}
+
+static void
+hn_polling(struct hn_softc *sc, u_int pollhz)
+{
+       int nsubch = sc->hn_rx_ring_inuse - 1;
+
+       HN_LOCK_ASSERT(sc);
+
+       if (nsubch > 0) {
+               struct vmbus_channel **subch;
+               int i;
+
+               subch = vmbus_subchan_get(sc->hn_prichan, nsubch);
+               for (i = 0; i < nsubch; ++i)
+                       hn_chan_polling(subch[i], pollhz);
+               vmbus_subchan_rel(subch, nsubch);
+       }
+       hn_chan_polling(sc->hn_prichan, pollhz);
+}
+
+static int
+hn_polling_sysctl(SYSCTL_HANDLER_ARGS)
+{
+       struct hn_softc *sc = arg1;
+       int pollhz, error;
+
+       pollhz = sc->hn_pollhz;
+       error = sysctl_handle_int(oidp, &pollhz, 0, req);
+       if (error || req->newptr == NULL)
+               return (error);
+
+       if (pollhz != 0 &&
+           (pollhz < VMBUS_CHAN_POLLHZ_MIN || pollhz > VMBUS_CHAN_POLLHZ_MAX))
+               return (EINVAL);
+
+       HN_LOCK(sc);
+       if (sc->hn_pollhz != pollhz) {
+               sc->hn_pollhz = pollhz;
+               if ((sc->hn_ifp->if_drv_flags & IFF_DRV_RUNNING) &&
+                   (sc->hn_flags & HN_FLAG_SYNTH_ATTACHED))
+                       hn_polling(sc, sc->hn_pollhz);
+       }
+       HN_UNLOCK(sc);
+
+       return (0);
+}
+
 static int
 hn_ndis_version_sysctl(SYSCTL_HANDLER_ARGS)
 {

Modified: head/sys/dev/hyperv/netvsc/if_hnvar.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/if_hnvar.h       Mon Dec 12 05:04:55 2016        
(r309874)
+++ head/sys/dev/hyperv/netvsc/if_hnvar.h       Mon Dec 12 05:18:03 2016        
(r309875)
@@ -212,6 +212,8 @@ struct hn_softc {
 
        uint32_t                hn_caps;        /* HN_CAP_ */
        uint32_t                hn_flags;       /* HN_FLAG_ */
+       u_int                   hn_pollhz;
+
        void                    *hn_rxbuf;
        uint32_t                hn_rxbuf_gpadl;
        struct hyperv_dma       hn_rxbuf_dma;
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to