Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
Show First 20 Lines • Show All 528 Lines • ▼ Show 20 Lines | SYSCTL_ADD_INT(ctx, child, OID_AUTO, "tx_chimney_max", | ||||
CTLFLAG_RD, &sc->hn_tx_chimney_max, 0, | CTLFLAG_RD, &sc->hn_tx_chimney_max, 0, | ||||
"Chimney send packet size upper boundary"); | "Chimney send packet size upper boundary"); | ||||
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "tx_chimney_size", | SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "tx_chimney_size", | ||||
CTLTYPE_INT | CTLFLAG_RW, sc, 0, hn_tx_chimney_size_sysctl, | CTLTYPE_INT | CTLFLAG_RW, sc, 0, hn_tx_chimney_size_sysctl, | ||||
"I", "Chimney send packet size limit"); | "I", "Chimney send packet size limit"); | ||||
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "direct_tx_size", | SYSCTL_ADD_INT(ctx, child, OID_AUTO, "direct_tx_size", | ||||
CTLFLAG_RW, &sc->hn_direct_tx_size, 0, | CTLFLAG_RW, &sc->hn_direct_tx_size, 0, | ||||
"Size of the packet for direct transmission"); | "Size of the packet for direct transmission"); | ||||
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "sched_tx", | |||||
CTLFLAG_RW, &sc->hn_sched_tx, 0, | |||||
"Always schedule transmission " | |||||
"instead of doing direct transmission"); | |||||
if (unit == 0) { | if (unit == 0) { | ||||
struct sysctl_ctx_list *dc_ctx; | struct sysctl_ctx_list *dc_ctx; | ||||
struct sysctl_oid_list *dc_child; | struct sysctl_oid_list *dc_child; | ||||
devclass_t dc; | devclass_t dc; | ||||
/* | /* | ||||
* Add sysctl nodes for devclass | * Add sysctl nodes for devclass | ||||
▲ Show 20 Lines • Show All 1,052 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* FreeBSD transmit entry point | * FreeBSD transmit entry point | ||||
*/ | */ | ||||
static void | static void | ||||
hn_start(struct ifnet *ifp) | hn_start(struct ifnet *ifp) | ||||
{ | { | ||||
hn_softc_t *sc; | struct hn_softc *sc = ifp->if_softc; | ||||
sc = ifp->if_softc; | if (sc->hn_sched_tx) | ||||
goto do_sched; | |||||
if (NV_TRYLOCK(sc)) { | if (NV_TRYLOCK(sc)) { | ||||
int sched; | int sched; | ||||
sched = hn_start_locked(ifp, sc->hn_direct_tx_size); | sched = hn_start_locked(ifp, sc->hn_direct_tx_size); | ||||
NV_UNLOCK(sc); | NV_UNLOCK(sc); | ||||
if (!sched) | if (!sched) | ||||
return; | return; | ||||
} | } | ||||
do_sched: | |||||
taskqueue_enqueue_fast(sc->hn_tx_taskq, &sc->hn_start_task); | taskqueue_enqueue_fast(sc->hn_tx_taskq, &sc->hn_start_task); | ||||
} | } | ||||
static void | static void | ||||
hn_start_txeof(struct ifnet *ifp) | hn_start_txeof(struct ifnet *ifp) | ||||
{ | { | ||||
hn_softc_t *sc; | struct hn_softc *sc = ifp->if_softc; | ||||
sc = ifp->if_softc; | if (sc->hn_sched_tx) | ||||
goto do_sched; | |||||
if (NV_TRYLOCK(sc)) { | if (NV_TRYLOCK(sc)) { | ||||
int sched; | int sched; | ||||
atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); | atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); | ||||
sched = hn_start_locked(ifp, sc->hn_direct_tx_size); | sched = hn_start_locked(ifp, sc->hn_direct_tx_size); | ||||
NV_UNLOCK(sc); | NV_UNLOCK(sc); | ||||
if (sched) { | if (sched) { | ||||
taskqueue_enqueue_fast(sc->hn_tx_taskq, | taskqueue_enqueue_fast(sc->hn_tx_taskq, | ||||
&sc->hn_start_task); | &sc->hn_start_task); | ||||
} | } | ||||
} else { | } else { | ||||
do_sched: | |||||
/* | /* | ||||
* Release the OACTIVE earlier, with the hope, that | * Release the OACTIVE earlier, with the hope, that | ||||
* others could catch up. The task will clear the | * others could catch up. The task will clear the | ||||
* flag again with the NV_LOCK to avoid possible | * flag again with the NV_LOCK to avoid possible | ||||
* races. | * races. | ||||
*/ | */ | ||||
atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); | atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); | ||||
taskqueue_enqueue_fast(sc->hn_tx_taskq, &sc->hn_txeof_task); | taskqueue_enqueue_fast(sc->hn_tx_taskq, &sc->hn_txeof_task); | ||||
▲ Show 20 Lines • Show All 397 Lines • Show Last 20 Lines |