Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153231515
D5074.id12702.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D5074.id12702.diff
View Options
Index: sys/dev/hyperv/netvsc/hv_net_vsc.h
===================================================================
--- sys/dev/hyperv/netvsc/hv_net_vsc.h
+++ sys/dev/hyperv/netvsc/hv_net_vsc.h
@@ -39,9 +39,11 @@
#define __HV_NET_VSC_H__
#include <sys/param.h>
+#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/queue.h>
+#include <sys/taskqueue.h>
#include <sys/sx.h>
#include <machine/bus.h>
@@ -1008,7 +1010,6 @@
struct hv_device *hn_dev_obj;
netvsc_dev *net_dev;
- int hn_txdesc_cnt;
struct hn_txdesc *hn_txdesc;
bus_dma_tag_t hn_tx_data_dtag;
bus_dma_tag_t hn_tx_rndis_dtag;
@@ -1017,9 +1018,15 @@
struct mtx hn_txlist_spin;
struct hn_txdesc_list hn_txlist;
+ int hn_txdesc_cnt;
int hn_txdesc_avail;
int hn_txeof;
+ int hn_direct_tx_size;
+ struct taskqueue *hn_tx_taskq;
+ struct task hn_start_task;
+ struct task hn_txeof_task;
+
struct lro_ctrl hn_lro;
int hn_lro_hiwat;
Index: sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
===================================================================
--- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
+++ sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
@@ -146,6 +146,8 @@
#define HN_TX_DATA_SEGCNT_MAX \
(NETVSC_PACKET_MAXPAGE - HV_RF_NUM_TX_RESERVED_PAGE_BUFS)
+#define HN_DIRECT_TX_SIZE_DEF 128
+
struct hn_txdesc {
SLIST_ENTRY(hn_txdesc) link;
struct mbuf *m;
@@ -194,6 +196,7 @@
#define NV_LOCK_INIT(_sc, _name) \
mtx_init(&(_sc)->hn_lock, _name, MTX_NETWORK_LOCK, MTX_DEF)
#define NV_LOCK(_sc) mtx_lock(&(_sc)->hn_lock)
+#define NV_TRYLOCK(_sc) mtx_trylock(&(_sc)->hn_lock)
#define NV_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->hn_lock, MA_OWNED)
#define NV_UNLOCK(_sc) mtx_unlock(&(_sc)->hn_lock)
#define NV_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->hn_lock)
@@ -219,6 +222,10 @@
static int hn_tx_chimney_size = 0;
TUNABLE_INT("dev.hn.tx_chimney_size", &hn_tx_chimney_size);
+/* Limit the size of packet for direct transmission */
+static int hn_direct_tx_size = HN_DIRECT_TX_SIZE_DEF;
+TUNABLE_INT("dev.hn.direct_tx_size", &hn_direct_tx_size);
+
/*
* Forward declarations
*/
@@ -226,8 +233,9 @@
static void hn_ifinit_locked(hn_softc_t *sc);
static void hn_ifinit(void *xsc);
static int hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
-static void hn_start_locked(struct ifnet *ifp);
+static int hn_start_locked(struct ifnet *ifp, int len);
static void hn_start(struct ifnet *ifp);
+static void hn_start_txeof(struct ifnet *ifp);
static int hn_ifmedia_upd(struct ifnet *ifp);
static void hn_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr);
#ifdef HN_LRO_HIWAT
@@ -237,6 +245,8 @@
static int hn_check_iplen(const struct mbuf *, int);
static int hn_create_tx_ring(struct hn_softc *sc);
static void hn_destroy_tx_ring(struct hn_softc *sc);
+static void hn_start_taskfunc(void *xsc, int pending);
+static void hn_txeof_taskfunc(void *xsc, int pending);
static __inline void
hn_set_lro_hiwat(struct hn_softc *sc, int hiwat)
@@ -384,6 +394,14 @@
sc->hn_dev = dev;
sc->hn_lro_hiwat = HN_LRO_HIWAT_DEF;
sc->hn_trust_hosttcp = hn_trust_hosttcp;
+ sc->hn_direct_tx_size = hn_direct_tx_size;
+
+ sc->hn_tx_taskq = taskqueue_create_fast("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));
+ TASK_INIT(&sc->hn_start_task, 0, hn_start_taskfunc, sc);
+ TASK_INIT(&sc->hn_txeof_task, 0, hn_txeof_taskfunc, sc);
error = hn_create_tx_ring(sc);
if (error)
@@ -524,6 +542,9 @@
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "tx_chimney_size",
CTLTYPE_INT | CTLFLAG_RW, sc, 0, hn_tx_chimney_size_sysctl,
"I", "Chimney send packet size limit");
+ SYSCTL_ADD_INT(ctx, child, OID_AUTO, "direct_tx_size",
+ CTLFLAG_RW, &sc->hn_direct_tx_size, 0,
+ "Size of the packet for direct transmission");
if (unit == 0) {
struct sysctl_ctx_list *dc_ctx;
@@ -548,6 +569,9 @@
SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "tso_maxlen",
CTLFLAG_RD, &hn_tso_maxlen, 0, "TSO burst limit");
#endif
+ SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "direct_tx_size",
+ CTLFLAG_RD, &hn_direct_tx_size, 0,
+ "Size of the packet for direct transmission");
}
return (0);
@@ -583,6 +607,10 @@
hv_rf_on_device_remove(hv_device, HV_RF_NV_DESTROY_CHANNEL);
+ taskqueue_drain(sc->hn_tx_taskq, &sc->hn_start_task);
+ taskqueue_drain(sc->hn_tx_taskq, &sc->hn_txeof_task);
+ taskqueue_free(sc->hn_tx_taskq);
+
ifmedia_removeall(&sc->hn_media);
#if defined(INET) || defined(INET6)
tcp_lro_free(&sc->hn_lro);
@@ -733,24 +761,19 @@
netvsc_channel_rollup(struct hv_device *device_ctx)
{
struct hn_softc *sc = device_get_softc(device_ctx->device);
- struct ifnet *ifp;
if (!sc->hn_txeof)
return;
sc->hn_txeof = 0;
- ifp = sc->hn_ifp;
- NV_LOCK(sc);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- hn_start_locked(ifp);
- NV_UNLOCK(sc);
+ hn_start_txeof(sc->hn_ifp);
}
/*
* Start a transmit of one or more packets
*/
-static void
-hn_start_locked(struct ifnet *ifp)
+static int
+hn_start_locked(struct ifnet *ifp, int len)
{
hn_softc_t *sc = ifp->if_softc;
struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev);
@@ -768,7 +791,7 @@
if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
IFF_DRV_RUNNING)
- return;
+ return 0;
while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
bus_dma_segment_t segs[HN_TX_DATA_SEGCNT_MAX];
@@ -781,11 +804,21 @@
if (m_head == NULL)
break;
+ if (len > 0 && m_head->m_pkthdr.len > len) {
+ /*
+ * This sending could be time consuming; let callers
+ * dispatch this packet sending (and sending of any
+ * following up packets) to tx taskqueue.
+ */
+ IF_PREPEND(&ifp->if_snd, m_head);
+ return 1;
+ }
+
txd = hn_txdesc_get(sc);
if (txd == NULL) {
sc->hn_no_txdescs++;
IF_PREPEND(&ifp->if_snd, m_head);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ atomic_set_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE);
break;
}
@@ -1060,10 +1093,11 @@
sc->hn_send_failed++;
IF_PREPEND(&ifp->if_snd, m_head);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ atomic_set_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE);
break;
}
}
+ return 0;
}
/*
@@ -1555,7 +1589,8 @@
if (bootverbose)
printf(" Closing Device ...\n");
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ atomic_clear_int(&ifp->if_drv_flags,
+ (IFF_DRV_RUNNING | IFF_DRV_OACTIVE));
if_link_state_change(ifp, LINK_STATE_DOWN);
sc->hn_initdone = 0;
@@ -1571,13 +1606,43 @@
hn_softc_t *sc;
sc = ifp->if_softc;
- NV_LOCK(sc);
- if (sc->temp_unusable) {
+ if (NV_TRYLOCK(sc)) {
+ int sched;
+
+ sched = hn_start_locked(ifp, sc->hn_direct_tx_size);
NV_UNLOCK(sc);
- return;
+ if (!sched)
+ return;
+ }
+ taskqueue_enqueue_fast(sc->hn_tx_taskq, &sc->hn_start_task);
+}
+
+static void
+hn_start_txeof(struct ifnet *ifp)
+{
+ hn_softc_t *sc;
+
+ sc = ifp->if_softc;
+ if (NV_TRYLOCK(sc)) {
+ int sched;
+
+ atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE);
+ sched = hn_start_locked(ifp, sc->hn_direct_tx_size);
+ NV_UNLOCK(sc);
+ if (sched) {
+ taskqueue_enqueue_fast(sc->hn_tx_taskq,
+ &sc->hn_start_task);
+ }
+ } else {
+ /*
+ * Release the OACTIVE earlier, with the hope, that
+ * others could catch up. The task will clear the
+ * flag again with the NV_LOCK to avoid possible
+ * races.
+ */
+ atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE);
+ taskqueue_enqueue_fast(sc->hn_tx_taskq, &sc->hn_txeof_task);
}
- hn_start_locked(ifp);
- NV_UNLOCK(sc);
}
/*
@@ -1604,8 +1669,8 @@
} else {
sc->hn_initdone = 1;
}
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE);
+ atomic_set_int(&ifp->if_drv_flags, IFF_DRV_RUNNING);
if_link_state_change(ifp, LINK_STATE_UP);
}
@@ -1907,6 +1972,28 @@
mtx_destroy(&sc->hn_txlist_spin);
}
+static void
+hn_start_taskfunc(void *xsc, int pending __unused)
+{
+ struct hn_softc *sc = xsc;
+
+ NV_LOCK(sc);
+ hn_start_locked(sc->hn_ifp, 0);
+ NV_UNLOCK(sc);
+}
+
+static void
+hn_txeof_taskfunc(void *xsc, int pending __unused)
+{
+ struct hn_softc *sc = xsc;
+ struct ifnet *ifp = sc->hn_ifp;
+
+ NV_LOCK(sc);
+ atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE);
+ hn_start_locked(ifp, 0);
+ NV_UNLOCK(sc);
+}
+
static device_method_t netvsc_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, netvsc_probe),
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 20, 11:15 PM (2 h, 58 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31870803
Default Alt Text
D5074.id12702.diff (8 KB)
Attached To
Mode
D5074: hyperv/hn: Improve sending performance
Attached
Detach File
Event Timeline
Log In to Comment