Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
Show First 20 Lines • Show All 339 Lines • ▼ Show 20 Lines | |||||
static void hn_start_txeof_taskfunc(void *, int); | static void hn_start_txeof_taskfunc(void *, int); | ||||
static void hn_stop_tx_tasks(struct hn_softc *); | static void hn_stop_tx_tasks(struct hn_softc *); | ||||
static int hn_encap(struct hn_tx_ring *, struct hn_txdesc *, struct mbuf **); | static int hn_encap(struct hn_tx_ring *, struct hn_txdesc *, struct mbuf **); | ||||
static void hn_create_rx_data(struct hn_softc *sc, int); | static void hn_create_rx_data(struct hn_softc *sc, int); | ||||
static void hn_destroy_rx_data(struct hn_softc *sc); | static void hn_destroy_rx_data(struct hn_softc *sc); | ||||
static void hn_set_tx_chimney_size(struct hn_softc *, int); | static void hn_set_tx_chimney_size(struct hn_softc *, int); | ||||
static void hn_channel_attach(struct hn_softc *, struct hv_vmbus_channel *); | static void hn_channel_attach(struct hn_softc *, struct hv_vmbus_channel *); | ||||
static void hn_subchan_attach(struct hn_softc *, struct hv_vmbus_channel *); | static void hn_subchan_attach(struct hn_softc *, struct hv_vmbus_channel *); | ||||
static void hn_subchan_setup(struct hn_softc *); | |||||
static int hn_transmit(struct ifnet *, struct mbuf *); | static int hn_transmit(struct ifnet *, struct mbuf *); | ||||
static void hn_xmit_qflush(struct ifnet *); | static void hn_xmit_qflush(struct ifnet *); | ||||
static int hn_xmit(struct hn_tx_ring *, int); | static int hn_xmit(struct hn_tx_ring *, int); | ||||
static void hn_xmit_txeof(struct hn_tx_ring *); | static void hn_xmit_txeof(struct hn_tx_ring *); | ||||
static void hn_xmit_taskfunc(void *, int); | static void hn_xmit_taskfunc(void *, int); | ||||
static void hn_xmit_txeof_taskfunc(void *, int); | static void hn_xmit_txeof_taskfunc(void *, int); | ||||
▲ Show 20 Lines • Show All 214 Lines • ▼ Show 20 Lines | #endif | ||||
* the # of channels that host offered. | * the # of channels that host offered. | ||||
*/ | */ | ||||
if (sc->hn_tx_ring_inuse > sc->net_dev->num_channel) | if (sc->hn_tx_ring_inuse > sc->net_dev->num_channel) | ||||
sc->hn_tx_ring_inuse = sc->net_dev->num_channel; | sc->hn_tx_ring_inuse = sc->net_dev->num_channel; | ||||
sc->hn_rx_ring_inuse = sc->net_dev->num_channel; | sc->hn_rx_ring_inuse = sc->net_dev->num_channel; | ||||
device_printf(dev, "%d TX ring, %d RX ring\n", | device_printf(dev, "%d TX ring, %d RX ring\n", | ||||
sc->hn_tx_ring_inuse, sc->hn_rx_ring_inuse); | sc->hn_tx_ring_inuse, sc->hn_rx_ring_inuse); | ||||
if (sc->net_dev->num_channel > 1) { | if (sc->net_dev->num_channel > 1) | ||||
struct hv_vmbus_channel **subchan; | hn_subchan_setup(sc); | ||||
int subchan_cnt = sc->net_dev->num_channel - 1; | |||||
int i; | |||||
/* Wait for sub-channels setup to complete. */ | |||||
subchan = vmbus_get_subchan(pri_chan, subchan_cnt); | |||||
/* Attach the sub-channels. */ | |||||
for (i = 0; i < subchan_cnt; ++i) { | |||||
/* NOTE: Calling order is critical. */ | |||||
hn_subchan_attach(sc, subchan[i]); | |||||
hv_nv_subchan_attach(subchan[i]); | |||||
} | |||||
/* Release the sub-channels */ | |||||
vmbus_rel_subchan(subchan, subchan_cnt); | |||||
device_printf(dev, "%d sub-channels setup done\n", subchan_cnt); | |||||
} | |||||
#if __FreeBSD_version >= 1100099 | #if __FreeBSD_version >= 1100099 | ||||
if (sc->hn_rx_ring_inuse > 1) { | if (sc->hn_rx_ring_inuse > 1) { | ||||
/* | /* | ||||
* Reduce TCP segment aggregation limit for multiple | * Reduce TCP segment aggregation limit for multiple | ||||
* RX rings to increase ACK timeliness. | * RX rings to increase ACK timeliness. | ||||
*/ | */ | ||||
hn_set_lro_lenlim(sc, HN_LRO_LENLIM_MULTIRX_DEF); | hn_set_lro_lenlim(sc, HN_LRO_LENLIM_MULTIRX_DEF); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,009 Lines • ▼ Show 20 Lines | #endif | ||||
*/ | */ | ||||
error = hv_rf_on_device_remove(hn_dev, HV_RF_NV_RETAIN_CHANNEL); | error = hv_rf_on_device_remove(hn_dev, HV_RF_NV_RETAIN_CHANNEL); | ||||
if (error) { | if (error) { | ||||
NV_LOCK(sc); | NV_LOCK(sc); | ||||
sc->temp_unusable = FALSE; | sc->temp_unusable = FALSE; | ||||
NV_UNLOCK(sc); | NV_UNLOCK(sc); | ||||
break; | break; | ||||
} | } | ||||
/* Wait for subchannels to be destroyed */ | |||||
vmbus_drain_subchan(hn_dev->channel); | |||||
error = hv_rf_on_device_add(hn_dev, &device_info, | error = hv_rf_on_device_add(hn_dev, &device_info, | ||||
sc->hn_rx_ring_inuse); | sc->hn_rx_ring_inuse); | ||||
if (error) { | if (error) { | ||||
NV_LOCK(sc); | NV_LOCK(sc); | ||||
sc->temp_unusable = FALSE; | sc->temp_unusable = FALSE; | ||||
NV_UNLOCK(sc); | NV_UNLOCK(sc); | ||||
break; | break; | ||||
} | } | ||||
KASSERT(sc->hn_rx_ring_cnt == sc->net_dev->num_channel, | |||||
("RX ring count %d and channel count %u mismatch", | |||||
sc->hn_rx_ring_cnt, sc->net_dev->num_channel)); | |||||
if (sc->net_dev->num_channel > 1) { | |||||
int r; | |||||
/* | |||||
* Skip the rings on primary channel; they are | |||||
* handled by the hv_rf_on_device_add() above. | |||||
*/ | |||||
for (r = 1; r < sc->hn_rx_ring_cnt; ++r) { | |||||
sc->hn_rx_ring[r].hn_rx_flags &= | |||||
~HN_RX_FLAG_ATTACHED; | |||||
} | |||||
for (r = 1; r < sc->hn_tx_ring_cnt; ++r) { | |||||
sc->hn_tx_ring[r].hn_tx_flags &= | |||||
~HN_TX_FLAG_ATTACHED; | |||||
} | |||||
hn_subchan_setup(sc); | |||||
} | |||||
sc->hn_tx_chimney_max = sc->net_dev->send_section_size; | sc->hn_tx_chimney_max = sc->net_dev->send_section_size; | ||||
if (sc->hn_tx_ring[0].hn_tx_chimney_size > | if (sc->hn_tx_ring[0].hn_tx_chimney_size > | ||||
sc->hn_tx_chimney_max) | sc->hn_tx_chimney_max) | ||||
hn_set_tx_chimney_size(sc, sc->hn_tx_chimney_max); | hn_set_tx_chimney_size(sc, sc->hn_tx_chimney_max); | ||||
hn_ifinit_locked(sc); | hn_ifinit_locked(sc); | ||||
NV_LOCK(sc); | NV_LOCK(sc); | ||||
▲ Show 20 Lines • Show All 1,332 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
KASSERT(!HV_VMBUS_CHAN_ISPRIMARY(chan), | KASSERT(!HV_VMBUS_CHAN_ISPRIMARY(chan), | ||||
("subchannel callback on primary channel")); | ("subchannel callback on primary channel")); | ||||
KASSERT(chan->offer_msg.offer.sub_channel_index > 0, | KASSERT(chan->offer_msg.offer.sub_channel_index > 0, | ||||
("invalid channel subidx %u", | ("invalid channel subidx %u", | ||||
chan->offer_msg.offer.sub_channel_index)); | chan->offer_msg.offer.sub_channel_index)); | ||||
hn_channel_attach(sc, chan); | hn_channel_attach(sc, chan); | ||||
} | |||||
static void | |||||
hn_subchan_setup(struct hn_softc *sc) | |||||
{ | |||||
struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev); | |||||
struct hv_vmbus_channel **subchan; | |||||
int subchan_cnt = sc->net_dev->num_channel - 1; | |||||
int i; | |||||
/* Wait for sub-channels setup to complete. */ | |||||
subchan = vmbus_get_subchan(device_ctx->channel, subchan_cnt); | |||||
/* Attach the sub-channels. */ | |||||
for (i = 0; i < subchan_cnt; ++i) { | |||||
/* NOTE: Calling order is critical. */ | |||||
hn_subchan_attach(sc, subchan[i]); | |||||
hv_nv_subchan_attach(subchan[i]); | |||||
} | |||||
/* Release the sub-channels */ | |||||
vmbus_rel_subchan(subchan, subchan_cnt); | |||||
if_printf(sc->hn_ifp, "%d sub-channels setup done\n", subchan_cnt); | |||||
} | } | ||||
static void | static void | ||||
hn_tx_taskq_create(void *arg __unused) | hn_tx_taskq_create(void *arg __unused) | ||||
{ | { | ||||
if (!hn_share_tx_taskq) | if (!hn_share_tx_taskq) | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 48 Lines • Show Last 20 Lines |