Date: Fri, 14 Oct 2016 02:34:04 +0000 (UTC) From: Sepherosa Ziehau <sephe@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r307247 - in stable/10/sys/dev/hyperv: include netvsc vmbus Message-ID: <201610140234.u9E2Y4Na052947@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sephe Date: Fri Oct 14 02:34:03 2016 New Revision: 307247 URL: https://svnweb.freebsd.org/changeset/base/307247 Log: MFC 306072-306074,306076 306072 hyperv/vmbus: Allow bufrings preallocation. The assumption that the channel is only opened upon synthetic device attach time no longer holds, e.g. Hyper-V network device MTU changes. We have to allow device drivers to preallocate bufrings, e.g. in attach DEVMETHOD, to prevent bufring allocation failure once the system memory is fragmented after running for a while. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7960 306073 hyperv/hn: Allocate bufrings in attach DEVMETHOD. So that reinitialization, e.g. MTU change, will not fail when the system memory is excessively fragmented. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7961 306074 hyperv/vmbus: Assert that the bufring address is page aligned. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7962 306076 hyperv/hn: Put debug messages under bootverbose While I'm here, strip blank line. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7963 Modified: stable/10/sys/dev/hyperv/include/vmbus.h stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/hyperv/include/vmbus.h ============================================================================== --- stable/10/sys/dev/hyperv/include/vmbus.h Fri Oct 14 02:27:19 2016 (r307246) +++ stable/10/sys/dev/hyperv/include/vmbus.h Fri Oct 14 02:34:03 2016 (r307247) @@ -109,6 +109,13 @@ struct vmbus_chanpkt_rxbuf { struct vmbus_rxbuf_desc cp_rxbuf[]; } __packed; +struct vmbus_chan_br { + void *cbr; + bus_addr_t cbr_paddr; + int cbr_txsz; + int cbr_rxsz; +}; + struct vmbus_channel; struct hyperv_guid; @@ -123,6 +130,9 @@ vmbus_get_channel(device_t dev) int vmbus_chan_open(struct vmbus_channel *chan, int txbr_size, int rxbr_size, const void *udata, int udlen, vmbus_chan_callback_t cb, void *cbarg); +int vmbus_chan_open_br(struct vmbus_channel *chan, + const struct vmbus_chan_br *cbr, const void *udata, + int udlen, vmbus_chan_callback_t cb, void *cbarg); void vmbus_chan_close(struct vmbus_channel *chan); int vmbus_chan_gpadl_connect(struct vmbus_channel *chan, Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h Fri Oct 14 02:27:19 2016 (r307246) +++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h Fri Oct 14 02:34:03 2016 (r307247) @@ -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: stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Fri Oct 14 02:27:19 2016 (r307246) +++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Fri Oct 14 02:34:03 2016 (r307247) @@ -2378,7 +2378,8 @@ hn_create_rx_data(struct hn_softc *sc, i lroent_cnt = hn_lro_entry_count; if (lroent_cnt < TCP_LRO_ENTRIES) lroent_cnt = TCP_LRO_ENTRIES; - device_printf(dev, "LRO: entry count %d\n", lroent_cnt); + if (bootverbose) + device_printf(dev, "LRO: entry count %d\n", lroent_cnt); #endif #endif /* INET || INET6 */ @@ -2392,6 +2393,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) @@ -2540,6 +2551,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 @@ -3145,6 +3161,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; @@ -3183,9 +3200,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); @@ -3328,8 +3350,10 @@ hn_synth_alloc_subchans(struct hn_softc *nsubch = 0; return (0); } - if_printf(sc->hn_ifp, "RX rings offered %u, requested %d\n", - rxr_cnt, nchan); + if (bootverbose) { + if_printf(sc->hn_ifp, "RX rings offered %u, requested %d\n", + rxr_cnt, nchan); + } if (nchan > rxr_cnt) nchan = rxr_cnt; @@ -3338,7 +3362,7 @@ hn_synth_alloc_subchans(struct hn_softc *nsubch = 0; return (0); } - + /* * Allocate sub-channels from NVS. */ Modified: stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c Fri Oct 14 02:27:19 2016 (r307246) +++ stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c Fri Oct 14 02:34:03 2016 (r307247) @@ -196,13 +196,45 @@ int vmbus_chan_open(struct vmbus_channel *chan, int txbr_size, int rxbr_size, const void *udata, int udlen, vmbus_chan_callback_t cb, void *cbarg) { + struct vmbus_chan_br cbr; + int error; + + /* + * Allocate the TX+RX bufrings. + */ + KASSERT(chan->ch_bufring == NULL, ("bufrings are allocated")); + chan->ch_bufring = hyperv_dmamem_alloc(bus_get_dma_tag(chan->ch_dev), + PAGE_SIZE, 0, txbr_size + rxbr_size, &chan->ch_bufring_dma, + BUS_DMA_WAITOK); + if (chan->ch_bufring == NULL) { + device_printf(chan->ch_dev, "bufring allocation failed\n"); + return (ENOMEM); + } + + cbr.cbr = chan->ch_bufring; + cbr.cbr_paddr = chan->ch_bufring_dma.hv_paddr; + cbr.cbr_txsz = txbr_size; + cbr.cbr_rxsz = rxbr_size; + + error = vmbus_chan_open_br(chan, &cbr, udata, udlen, cb, cbarg); + if (error) { + hyperv_dmamem_free(&chan->ch_bufring_dma, chan->ch_bufring); + chan->ch_bufring = NULL; + } + return (error); +} + +int +vmbus_chan_open_br(struct vmbus_channel *chan, const struct vmbus_chan_br *cbr, + const void *udata, int udlen, vmbus_chan_callback_t cb, void *cbarg) +{ struct vmbus_softc *sc = chan->ch_vmbus; const struct vmbus_chanmsg_chopen_resp *resp; const struct vmbus_message *msg; struct vmbus_chanmsg_chopen *req; struct vmbus_msghc *mh; uint32_t status; - int error; + int error, txbr_size, rxbr_size; uint8_t *br; if (udlen > VMBUS_CHANMSG_CHOPEN_UDATA_SIZE) { @@ -210,10 +242,21 @@ vmbus_chan_open(struct vmbus_channel *ch "invalid udata len %d for chan%u\n", udlen, chan->ch_id); return EINVAL; } + + br = cbr->cbr; + txbr_size = cbr->cbr_txsz; + rxbr_size = cbr->cbr_rxsz; KASSERT((txbr_size & PAGE_MASK) == 0, ("send bufring size is not multiple page")); KASSERT((rxbr_size & PAGE_MASK) == 0, ("recv bufring size is not multiple page")); + KASSERT((cbr->cbr_paddr & PAGE_MASK) == 0, + ("bufring is not page aligned")); + + /* + * Zero out the TX/RX bufrings, in case that they were used before. + */ + memset(br, 0, txbr_size + rxbr_size); if (atomic_testandset_int(&chan->ch_stflags, VMBUS_CHAN_ST_OPENED_SHIFT)) @@ -230,20 +273,6 @@ vmbus_chan_open(struct vmbus_channel *ch else TASK_INIT(&chan->ch_task, 0, vmbus_chan_task_nobatch, chan); - /* - * Allocate the TX+RX bufrings. - * XXX should use ch_dev dtag - */ - br = hyperv_dmamem_alloc(bus_get_dma_tag(sc->vmbus_dev), - PAGE_SIZE, 0, txbr_size + rxbr_size, &chan->ch_bufring_dma, - BUS_DMA_WAITOK | BUS_DMA_ZERO); - if (br == NULL) { - device_printf(sc->vmbus_dev, "bufring allocation failed\n"); - error = ENOMEM; - goto failed; - } - chan->ch_bufring = br; - /* TX bufring comes first */ vmbus_txbr_setup(&chan->ch_txbr, br, txbr_size); /* RX bufring immediately follows TX bufring */ @@ -255,7 +284,7 @@ vmbus_chan_open(struct vmbus_channel *ch /* * Connect the bufrings, both RX and TX, to this channel. */ - error = vmbus_chan_gpadl_connect(chan, chan->ch_bufring_dma.hv_paddr, + error = vmbus_chan_gpadl_connect(chan, cbr->cbr_paddr, txbr_size + rxbr_size, &chan->ch_bufring_gpadl); if (error) { device_printf(sc->vmbus_dev, @@ -316,10 +345,6 @@ failed: vmbus_chan_gpadl_disconnect(chan, chan->ch_bufring_gpadl); chan->ch_bufring_gpadl = 0; } - if (chan->ch_bufring != NULL) { - hyperv_dmamem_free(&chan->ch_bufring_dma, chan->ch_bufring); - chan->ch_bufring = NULL; - } atomic_clear_int(&chan->ch_stflags, VMBUS_CHAN_ST_OPENED); return error; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201610140234.u9E2Y4Na052947>