Author: sephe
Date: Wed Sep 21 06:27:42 2016
New Revision: 306073
URL: https://svnweb.freebsd.org/changeset/base/306073

Log:
  hyperv/hn: Allocate bufrings in attach DEVMETHOD.
  
  So that reinitialization, e.g. MTU change, will not fail when the system
  memory is excessively fragmented.
  
  MFC after:    1 week
  Sponsored by: Microsoft
  Differential Revision:        https://reviews.freebsd.org/D7961

Modified:
  head/sys/dev/hyperv/netvsc/hv_net_vsc.h
  head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c

Modified: head/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_net_vsc.h     Wed Sep 21 05:56:47 2016        
(r306072)
+++ head/sys/dev/hyperv/netvsc/hv_net_vsc.h     Wed Sep 21 06:27:42 2016        
(r306073)
@@ -136,6 +136,9 @@ struct hn_rx_ring {
        /* Rarely used stuffs */
        struct sysctl_oid *hn_rx_sysctl_tree;
        int             hn_rx_flags;
+
+       void            *hn_br;         /* TX/RX bufring */
+       struct hyperv_dma hn_br_dma;
 } __aligned(CACHE_LINE_SIZE);
 
 #define HN_TRUST_HCSUM_IP      0x0001

Modified: head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c  Wed Sep 21 05:56:47 
2016        (r306072)
+++ head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c  Wed Sep 21 06:27:42 
2016        (r306073)
@@ -2372,6 +2372,16 @@ hn_create_rx_data(struct hn_softc *sc, i
        for (i = 0; i < sc->hn_rx_ring_cnt; ++i) {
                struct hn_rx_ring *rxr = &sc->hn_rx_ring[i];
 
+               rxr->hn_br = hyperv_dmamem_alloc(bus_get_dma_tag(dev),
+                   PAGE_SIZE, 0,
+                   NETVSC_DEVICE_RING_BUFFER_SIZE +
+                   NETVSC_DEVICE_RING_BUFFER_SIZE,
+                   &rxr->hn_br_dma, BUS_DMA_WAITOK);
+               if (rxr->hn_br == NULL) {
+                       device_printf(dev, "allocate bufring failed\n");
+                       return (ENOMEM);
+               }
+
                if (hn_trust_hosttcp)
                        rxr->hn_trust_hcsum |= HN_TRUST_HCSUM_TCP;
                if (hn_trust_hostudp)
@@ -2520,6 +2530,11 @@ hn_destroy_rx_data(struct hn_softc *sc)
        for (i = 0; i < sc->hn_rx_ring_cnt; ++i) {
                struct hn_rx_ring *rxr = &sc->hn_rx_ring[i];
 
+               if (rxr->hn_br == NULL)
+                       continue;
+               hyperv_dmamem_free(&rxr->hn_br_dma, rxr->hn_br);
+               rxr->hn_br = NULL;
+
 #if defined(INET) || defined(INET6)
                tcp_lro_free(&rxr->hn_lro);
 #endif
@@ -3125,6 +3140,7 @@ hn_xmit_txeof_taskfunc(void *xtxr, int p
 static int
 hn_chan_attach(struct hn_softc *sc, struct vmbus_channel *chan)
 {
+       struct vmbus_chan_br cbr;
        struct hn_rx_ring *rxr;
        struct hn_tx_ring *txr = NULL;
        int idx, error;
@@ -3163,9 +3179,14 @@ hn_chan_attach(struct hn_softc *sc, stru
        /* Bind this channel to a proper CPU. */
        vmbus_chan_cpu_set(chan, (sc->hn_cpu + idx) % mp_ncpus);
 
-       /* Open this channel */
-       error = vmbus_chan_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE,
-           NETVSC_DEVICE_RING_BUFFER_SIZE, NULL, 0, hn_chan_callback, rxr);
+       /*
+        * Open this channel
+        */
+       cbr.cbr = rxr->hn_br;
+       cbr.cbr_paddr = rxr->hn_br_dma.hv_paddr;
+       cbr.cbr_txsz = NETVSC_DEVICE_RING_BUFFER_SIZE;
+       cbr.cbr_rxsz = NETVSC_DEVICE_RING_BUFFER_SIZE;
+       error = vmbus_chan_open_br(chan, &cbr, NULL, 0, hn_chan_callback, rxr);
        if (error) {
                if_printf(sc->hn_ifp, "open chan%u failed: %d\n",
                    vmbus_chan_id(chan), error);
_______________________________________________
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