hyperv/hn: Allow multiple TX taskqueues.

MFC after:	1 week
Sponsored by:	Microsoft
Differential Revision:	https://reviews.freebsd.org/D8655
This commit is contained in:
Sepherosa Ziehau 2016-11-30 05:28:39 +00:00
parent 52d8123421
commit fdd0222a04
2 changed files with 52 additions and 16 deletions

View File

@ -416,6 +416,10 @@ static int hn_share_tx_taskq = 0;
SYSCTL_INT(_hw_hn, OID_AUTO, share_tx_taskq, CTLFLAG_RDTUN,
&hn_share_tx_taskq, 0, "Enable shared TX taskqueue");
static int hn_tx_taskq_cnt = 1;
SYSCTL_INT(_hw_hn, OID_AUTO, tx_taskq_cnt, CTLFLAG_RDTUN,
&hn_tx_taskq_cnt, 0, "# of TX taskqueues");
#ifndef HN_USE_TXDESC_BUFRING
static int hn_use_txdesc_bufring = 0;
#else
@ -465,7 +469,7 @@ SYSCTL_INT(_hw_hn, OID_AUTO, tx_agg_pkts, CTLFLAG_RDTUN,
&hn_tx_agg_pkts, 0, "Packet transmission aggregation packet limit");
static u_int hn_cpu_index; /* next CPU for channel */
static struct taskqueue *hn_tx_taskq; /* shared TX taskqueue */
static struct taskqueue **hn_tx_taskque;/* shared TX taskqueues */
static const uint8_t
hn_rss_key_default[NDIS_HASH_KEYSIZE_TOEPLITZ] = {
@ -898,13 +902,21 @@ hn_attach(device_t dev)
/*
* Setup taskqueue for transmission.
*/
if (hn_tx_taskq == NULL) {
sc->hn_tx_taskq = taskqueue_create("hn_tx", M_WAITOK,
taskqueue_thread_enqueue, &sc->hn_tx_taskq);
taskqueue_start_threads(&sc->hn_tx_taskq, 1, PI_NET, "%s tx",
device_get_nameunit(dev));
if (hn_tx_taskque == NULL) {
int i;
sc->hn_tx_taskqs =
malloc(hn_tx_taskq_cnt * sizeof(struct taskqueue *),
M_DEVBUF, M_WAITOK);
for (i = 0; i < hn_tx_taskq_cnt; ++i) {
sc->hn_tx_taskqs[i] = taskqueue_create("hn_tx",
M_WAITOK, taskqueue_thread_enqueue,
&sc->hn_tx_taskqs[i]);
taskqueue_start_threads(&sc->hn_tx_taskqs[i], 1, PI_NET,
"%s tx%d", device_get_nameunit(dev), i);
}
} else {
sc->hn_tx_taskq = hn_tx_taskq;
sc->hn_tx_taskqs = hn_tx_taskque;
}
/*
@ -1204,8 +1216,13 @@ hn_detach(device_t dev)
hn_destroy_rx_data(sc);
hn_destroy_tx_data(sc);
if (sc->hn_tx_taskq != hn_tx_taskq)
taskqueue_free(sc->hn_tx_taskq);
if (sc->hn_tx_taskqs != hn_tx_taskque) {
int i;
for (i = 0; i < hn_tx_taskq_cnt; ++i)
taskqueue_free(sc->hn_tx_taskqs[i]);
free(sc->hn_tx_taskqs, M_DEVBUF);
}
taskqueue_free(sc->hn_mgmt_taskq0);
if (sc->hn_xact != NULL) {
@ -3295,7 +3312,7 @@ hn_tx_ring_create(struct hn_softc *sc, int id)
M_WAITOK, &txr->hn_tx_lock);
#endif
txr->hn_tx_taskq = sc->hn_tx_taskq;
txr->hn_tx_taskq = sc->hn_tx_taskqs[id % hn_tx_taskq_cnt];
#ifdef HN_IFSTART_SUPPORT
if (hn_use_if_start) {
@ -5334,6 +5351,15 @@ hn_chan_callback(struct vmbus_channel *chan, void *xrxr)
static void
hn_tx_taskq_create(void *arg __unused)
{
int i;
/*
* Fix the # of TX taskqueues.
*/
if (hn_tx_taskq_cnt <= 0)
hn_tx_taskq_cnt = 1;
else if (hn_tx_taskq_cnt > mp_ncpus)
hn_tx_taskq_cnt = mp_ncpus;
if (vm_guest != VM_GUEST_HV)
return;
@ -5341,9 +5367,14 @@ hn_tx_taskq_create(void *arg __unused)
if (!hn_share_tx_taskq)
return;
hn_tx_taskq = taskqueue_create("hn_tx", M_WAITOK,
taskqueue_thread_enqueue, &hn_tx_taskq);
taskqueue_start_threads(&hn_tx_taskq, 1, PI_NET, "hn tx");
hn_tx_taskque = malloc(hn_tx_taskq_cnt * sizeof(struct taskqueue *),
M_DEVBUF, M_WAITOK);
for (i = 0; i < hn_tx_taskq_cnt; ++i) {
hn_tx_taskque[i] = taskqueue_create("hn_tx", M_WAITOK,
taskqueue_thread_enqueue, &hn_tx_taskque[i]);
taskqueue_start_threads(&hn_tx_taskque[i], 1, PI_NET,
"hn tx%d", i);
}
}
SYSINIT(hn_txtq_create, SI_SUB_DRIVERS, SI_ORDER_SECOND,
hn_tx_taskq_create, NULL);
@ -5352,8 +5383,13 @@ static void
hn_tx_taskq_destroy(void *arg __unused)
{
if (hn_tx_taskq != NULL)
taskqueue_free(hn_tx_taskq);
if (hn_tx_taskque != NULL) {
int i;
for (i = 0; i < hn_tx_taskq_cnt; ++i)
taskqueue_free(hn_tx_taskque[i]);
free(hn_tx_taskque, M_DEVBUF);
}
}
SYSUNINIT(hn_txtq_destroy, SI_SUB_DRIVERS, SI_ORDER_SECOND,
hn_tx_taskq_destroy, NULL);

View File

@ -192,7 +192,7 @@ struct hn_softc {
int hn_chim_szmax;
int hn_cpu;
struct taskqueue *hn_tx_taskq;
struct taskqueue **hn_tx_taskqs;
struct sysctl_oid *hn_tx_sysctl_tree;
struct sysctl_oid *hn_rx_sysctl_tree;
struct vmbus_xact_ctx *hn_xact;