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
This commit is contained in:
Sepherosa Ziehau 2016-10-31 04:46:02 +00:00
parent e6ed06f904
commit 8ff20a73f6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=308117
2 changed files with 59 additions and 50 deletions

View File

@ -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, int ring_cnt)
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, int ring_cnt)
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 *chan, void *xrxr)
{
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;
for (;;) {
struct vmbus_chanpkt_hdr *pkt = rxr->hn_pktbuf;
int error, pktlen;
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;
}
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));
if (bufferlen > HN_PKTBUF_LEN)
free(buffer, M_DEVBUF);
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;
}
}
hn_chan_rollup(rxr, rxr->hn_txr);
}

View File

@ -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;