svn commit: r308117 - head/sys/dev/hyperv/netvsc
Sepherosa Ziehau
sephe at FreeBSD.org
Mon Oct 31 04:46:03 UTC 2016
Author: sephe
Date: Mon Oct 31 04:46:02 2016
New Revision: 308117
URL: https://svnweb.freebsd.org/changeset/base/308117
Log:
hyperv/hn: Rework temporary channel packet buffer expanding.
And use large default temporary channel packer buffer; we really
don't want it to be expanded at run time.
MFC after: 1 week
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D8367
Modified:
head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
head/sys/dev/hyperv/netvsc/if_hnvar.h
Modified: head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Mon Oct 31 01:36:28 2016 (r308116)
+++ head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Mon Oct 31 04:46:02 2016 (r308117)
@@ -176,6 +176,8 @@ __FBSDID("$FreeBSD$");
HN_RXINFO_HASHINF | \
HN_RXINFO_HASHVAL)
+#define HN_PKTBUF_LEN_DEF (16 * 1024)
+
struct hn_txdesc {
#ifndef HN_USE_TXDESC_BUFRING
SLIST_ENTRY(hn_txdesc) link;
@@ -2720,7 +2722,8 @@ hn_create_rx_data(struct hn_softc *sc, i
rxr->hn_ifp = sc->hn_ifp;
if (i < sc->hn_tx_ring_cnt)
rxr->hn_txr = &sc->hn_tx_ring[i];
- rxr->hn_pktbuf = malloc(HN_PKTBUF_LEN, M_DEVBUF, M_WAITOK);
+ rxr->hn_pktbuf_len = HN_PKTBUF_LEN_DEF;
+ rxr->hn_pktbuf = malloc(rxr->hn_pktbuf_len, M_DEVBUF, M_WAITOK);
rxr->hn_rx_idx = i;
rxr->hn_rxbuf = sc->hn_rxbuf;
@@ -2763,6 +2766,11 @@ hn_create_rx_data(struct hn_softc *sc, i
OID_AUTO, "rss_pkts", CTLFLAG_RW,
&rxr->hn_rss_pkts,
"# of packets w/ RSS info received");
+ SYSCTL_ADD_INT(ctx,
+ SYSCTL_CHILDREN(rxr->hn_rx_sysctl_tree),
+ OID_AUTO, "pktbuf_len", CTLFLAG_RD,
+ &rxr->hn_pktbuf_len, 0,
+ "Temporary channel packet buffer length");
}
}
}
@@ -4536,60 +4544,62 @@ hn_chan_callback(struct vmbus_channel *c
{
struct hn_rx_ring *rxr = xrxr;
struct hn_softc *sc = rxr->hn_ifp->if_softc;
- void *buffer;
- int bufferlen = HN_PKTBUF_LEN;
- buffer = rxr->hn_pktbuf;
- do {
- struct vmbus_chanpkt_hdr *pkt = buffer;
- uint32_t bytes_rxed;
- int ret;
-
- bytes_rxed = bufferlen;
- ret = vmbus_chan_recv_pkt(chan, pkt, &bytes_rxed);
- if (ret == 0) {
- switch (pkt->cph_type) {
- case VMBUS_CHANPKT_TYPE_COMP:
- hn_nvs_handle_comp(sc, chan, pkt);
- break;
- case VMBUS_CHANPKT_TYPE_RXBUF:
- hn_nvs_handle_rxbuf(rxr, chan, pkt);
- break;
- case VMBUS_CHANPKT_TYPE_INBAND:
- hn_nvs_handle_notify(sc, pkt);
- break;
- default:
- if_printf(rxr->hn_ifp,
- "unknown chan pkt %u\n",
- pkt->cph_type);
- break;
- }
- } else if (ret == ENOBUFS) {
- /* Handle large packet */
- if (bufferlen > HN_PKTBUF_LEN) {
- free(buffer, M_DEVBUF);
- buffer = NULL;
- }
+ for (;;) {
+ struct vmbus_chanpkt_hdr *pkt = rxr->hn_pktbuf;
+ int error, pktlen;
+
+ pktlen = rxr->hn_pktbuf_len;
+ error = vmbus_chan_recv_pkt(chan, pkt, &pktlen);
+ if (__predict_false(error == ENOBUFS)) {
+ void *nbuf;
+ int nlen;
- /* alloc new buffer */
- buffer = malloc(bytes_rxed, M_DEVBUF, M_NOWAIT);
- if (buffer == NULL) {
- if_printf(rxr->hn_ifp,
- "hv_cb malloc buffer failed, len=%u\n",
- bytes_rxed);
- bufferlen = 0;
- break;
- }
- bufferlen = bytes_rxed;
- } else {
- /* No more packets */
+ /*
+ * Expand channel packet buffer.
+ *
+ * XXX
+ * Use M_WAITOK here, since allocation failure
+ * is fatal.
+ */
+ nlen = rxr->hn_pktbuf_len * 2;
+ while (nlen < pktlen)
+ nlen *= 2;
+ nbuf = malloc(nlen, M_DEVBUF, M_WAITOK);
+
+ if_printf(rxr->hn_ifp, "expand pktbuf %d -> %d\n",
+ rxr->hn_pktbuf_len, nlen);
+
+ free(rxr->hn_pktbuf, M_DEVBUF);
+ rxr->hn_pktbuf = nbuf;
+ rxr->hn_pktbuf_len = nlen;
+ /* Retry! */
+ continue;
+ } else if (__predict_false(error == EAGAIN)) {
+ /* No more channel packets; done! */
break;
}
- } while (1);
+ KASSERT(!error, ("vmbus_chan_recv_pkt failed: %d", error));
+
+ switch (pkt->cph_type) {
+ case VMBUS_CHANPKT_TYPE_COMP:
+ hn_nvs_handle_comp(sc, chan, pkt);
+ break;
- if (bufferlen > HN_PKTBUF_LEN)
- free(buffer, M_DEVBUF);
+ case VMBUS_CHANPKT_TYPE_RXBUF:
+ hn_nvs_handle_rxbuf(rxr, chan, pkt);
+ break;
+ case VMBUS_CHANPKT_TYPE_INBAND:
+ hn_nvs_handle_notify(sc, pkt);
+ break;
+
+ default:
+ if_printf(rxr->hn_ifp, "unknown chan pkt %u\n",
+ pkt->cph_type);
+ break;
+ }
+ }
hn_chan_rollup(rxr, rxr->hn_txr);
}
Modified: head/sys/dev/hyperv/netvsc/if_hnvar.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/if_hnvar.h Mon Oct 31 01:36:28 2016 (r308116)
+++ head/sys/dev/hyperv/netvsc/if_hnvar.h Mon Oct 31 04:46:02 2016 (r308117)
@@ -39,8 +39,6 @@
/* Claimed to be 12232B */
#define HN_MTU_MAX (9 * 1024)
-#define HN_PKTBUF_LEN 4096
-
#define HN_TXBR_SIZE (128 * PAGE_SIZE)
#define HN_RXBR_SIZE (128 * PAGE_SIZE)
@@ -63,6 +61,7 @@ struct hn_rx_ring {
struct ifnet *hn_ifp;
struct hn_tx_ring *hn_txr;
void *hn_pktbuf;
+ int hn_pktbuf_len;
uint8_t *hn_rxbuf; /* shadow sc->hn_rxbuf */
int hn_rx_idx;
More information about the svn-src-head
mailing list