Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
Show First 20 Lines • Show All 336 Lines • ▼ Show 20 Lines | |||||
static int hn_create_tx_ring(struct hn_softc *, int); | static int hn_create_tx_ring(struct hn_softc *, int); | ||||
static void hn_destroy_tx_ring(struct hn_tx_ring *); | static void hn_destroy_tx_ring(struct hn_tx_ring *); | ||||
static int hn_create_tx_data(struct hn_softc *, int); | static int hn_create_tx_data(struct hn_softc *, int); | ||||
static void hn_destroy_tx_data(struct hn_softc *); | static void hn_destroy_tx_data(struct hn_softc *); | ||||
static void hn_start_taskfunc(void *, int); | static void hn_start_taskfunc(void *, int); | ||||
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 int 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 vmbus_channel *); | static void hn_channel_attach(struct hn_softc *, struct vmbus_channel *); | ||||
static void hn_subchan_attach(struct hn_softc *, struct vmbus_channel *); | static void hn_subchan_attach(struct hn_softc *, struct vmbus_channel *); | ||||
static void hn_subchan_setup(struct hn_softc *); | 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 *); | ||||
▲ Show 20 Lines • Show All 145 Lines • ▼ Show 20 Lines | #endif | ||||
/* | /* | ||||
* Set the leader CPU for channels. | * Set the leader CPU for channels. | ||||
*/ | */ | ||||
sc->hn_cpu = atomic_fetchadd_int(&hn_cpu_index, ring_cnt) % mp_ncpus; | sc->hn_cpu = atomic_fetchadd_int(&hn_cpu_index, ring_cnt) % mp_ncpus; | ||||
error = hn_create_tx_data(sc, tx_ring_cnt); | error = hn_create_tx_data(sc, tx_ring_cnt); | ||||
if (error) | if (error) | ||||
goto failed; | goto failed; | ||||
hn_create_rx_data(sc, ring_cnt); | error = hn_create_rx_data(sc, ring_cnt); | ||||
if (error) | |||||
goto failed; | |||||
/* | /* | ||||
* Associate the first TX/RX ring w/ the primary channel. | * Associate the first TX/RX ring w/ the primary channel. | ||||
*/ | */ | ||||
hn_channel_attach(sc, sc->hn_prichan); | hn_channel_attach(sc, sc->hn_prichan); | ||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | ||||
ifp->if_ioctl = hn_ioctl; | ifp->if_ioctl = hn_ioctl; | ||||
▲ Show 20 Lines • Show All 1,655 Lines • ▼ Show 20 Lines | hn_check_iplen(const struct mbuf *m, int hoff) | ||||
default: | default: | ||||
if (iplen < iphlen) | if (iplen < iphlen) | ||||
return IPPROTO_DONE; | return IPPROTO_DONE; | ||||
break; | break; | ||||
} | } | ||||
return ip->ip_p; | return ip->ip_p; | ||||
} | } | ||||
static void | static int | ||||
hn_create_rx_data(struct hn_softc *sc, int ring_cnt) | hn_create_rx_data(struct hn_softc *sc, int ring_cnt) | ||||
{ | { | ||||
struct sysctl_oid_list *child; | struct sysctl_oid_list *child; | ||||
struct sysctl_ctx_list *ctx; | struct sysctl_ctx_list *ctx; | ||||
device_t dev = sc->hn_dev; | device_t dev = sc->hn_dev; | ||||
#if defined(INET) || defined(INET6) | #if defined(INET) || defined(INET6) | ||||
#if __FreeBSD_version >= 1100095 | #if __FreeBSD_version >= 1100095 | ||||
int lroent_cnt; | int lroent_cnt; | ||||
#endif | #endif | ||||
#endif | #endif | ||||
int i; | int i; | ||||
/* | |||||
* Create RXBUF for reception. | |||||
* | |||||
* NOTE: | |||||
* - It is shared by all channels. | |||||
* - A large enough buffer is allocated, certain version of NVSes | |||||
* may further limit the usable space. | |||||
*/ | |||||
sc->hn_rxbuf = hyperv_dmamem_alloc(bus_get_dma_tag(dev), | |||||
PAGE_SIZE, 0, NETVSC_RECEIVE_BUFFER_SIZE, &sc->hn_rxbuf_dma, | |||||
BUS_DMA_WAITOK | BUS_DMA_ZERO); | |||||
if (sc->hn_rxbuf == NULL) { | |||||
device_printf(sc->hn_dev, "allocate rxbuf failed\n"); | |||||
return (ENOMEM); | |||||
} | |||||
sc->hn_rx_ring_cnt = ring_cnt; | sc->hn_rx_ring_cnt = ring_cnt; | ||||
sc->hn_rx_ring_inuse = sc->hn_rx_ring_cnt; | sc->hn_rx_ring_inuse = sc->hn_rx_ring_cnt; | ||||
sc->hn_rx_ring = malloc(sizeof(struct hn_rx_ring) * sc->hn_rx_ring_cnt, | sc->hn_rx_ring = malloc(sizeof(struct hn_rx_ring) * sc->hn_rx_ring_cnt, | ||||
M_NETVSC, M_WAITOK | M_ZERO); | M_NETVSC, M_WAITOK | M_ZERO); | ||||
#if defined(INET) || defined(INET6) | #if defined(INET) || defined(INET6) | ||||
#if __FreeBSD_version >= 1100095 | #if __FreeBSD_version >= 1100095 | ||||
Show All 20 Lines | if (hn_trust_hostudp) | ||||
rxr->hn_trust_hcsum |= HN_TRUST_HCSUM_UDP; | rxr->hn_trust_hcsum |= HN_TRUST_HCSUM_UDP; | ||||
if (hn_trust_hostip) | if (hn_trust_hostip) | ||||
rxr->hn_trust_hcsum |= HN_TRUST_HCSUM_IP; | rxr->hn_trust_hcsum |= HN_TRUST_HCSUM_IP; | ||||
rxr->hn_ifp = sc->hn_ifp; | rxr->hn_ifp = sc->hn_ifp; | ||||
if (i < sc->hn_tx_ring_cnt) | if (i < sc->hn_tx_ring_cnt) | ||||
rxr->hn_txr = &sc->hn_tx_ring[i]; | rxr->hn_txr = &sc->hn_tx_ring[i]; | ||||
rxr->hn_rdbuf = malloc(NETVSC_PACKET_SIZE, M_NETVSC, M_WAITOK); | rxr->hn_rdbuf = malloc(NETVSC_PACKET_SIZE, M_NETVSC, M_WAITOK); | ||||
rxr->hn_rx_idx = i; | rxr->hn_rx_idx = i; | ||||
rxr->hn_rxbuf = sc->hn_rxbuf; | |||||
/* | /* | ||||
* Initialize LRO. | * Initialize LRO. | ||||
*/ | */ | ||||
#if defined(INET) || defined(INET6) | #if defined(INET) || defined(INET6) | ||||
#if __FreeBSD_version >= 1100095 | #if __FreeBSD_version >= 1100095 | ||||
tcp_lro_init_args(&rxr->hn_lro, sc->hn_ifp, lroent_cnt, | tcp_lro_init_args(&rxr->hn_lro, sc->hn_ifp, lroent_cnt, | ||||
hn_lro_mbufq_depth); | hn_lro_mbufq_depth); | ||||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | #endif | ||||
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "small_pkts", | SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "small_pkts", | ||||
CTLTYPE_ULONG | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, | CTLTYPE_ULONG | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, | ||||
__offsetof(struct hn_rx_ring, hn_small_pkts), | __offsetof(struct hn_rx_ring, hn_small_pkts), | ||||
hn_rx_stat_ulong_sysctl, "LU", "# of small packets received"); | hn_rx_stat_ulong_sysctl, "LU", "# of small packets received"); | ||||
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "rx_ring_cnt", | SYSCTL_ADD_INT(ctx, child, OID_AUTO, "rx_ring_cnt", | ||||
CTLFLAG_RD, &sc->hn_rx_ring_cnt, 0, "# created RX rings"); | CTLFLAG_RD, &sc->hn_rx_ring_cnt, 0, "# created RX rings"); | ||||
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "rx_ring_inuse", | SYSCTL_ADD_INT(ctx, child, OID_AUTO, "rx_ring_inuse", | ||||
CTLFLAG_RD, &sc->hn_rx_ring_inuse, 0, "# used RX rings"); | CTLFLAG_RD, &sc->hn_rx_ring_inuse, 0, "# used RX rings"); | ||||
return (0); | |||||
} | } | ||||
static void | static void | ||||
hn_destroy_rx_data(struct hn_softc *sc) | hn_destroy_rx_data(struct hn_softc *sc) | ||||
{ | { | ||||
int i; | int i; | ||||
if (sc->hn_rx_ring_cnt == 0) | if (sc->hn_rx_ring_cnt == 0) | ||||
return; | return; | ||||
for (i = 0; i < sc->hn_rx_ring_cnt; ++i) { | for (i = 0; i < sc->hn_rx_ring_cnt; ++i) { | ||||
struct hn_rx_ring *rxr = &sc->hn_rx_ring[i]; | struct hn_rx_ring *rxr = &sc->hn_rx_ring[i]; | ||||
#if defined(INET) || defined(INET6) | #if defined(INET) || defined(INET6) | ||||
tcp_lro_free(&rxr->hn_lro); | tcp_lro_free(&rxr->hn_lro); | ||||
#endif | #endif | ||||
free(rxr->hn_rdbuf, M_NETVSC); | free(rxr->hn_rdbuf, M_NETVSC); | ||||
} | } | ||||
free(sc->hn_rx_ring, M_NETVSC); | free(sc->hn_rx_ring, M_NETVSC); | ||||
sc->hn_rx_ring = NULL; | sc->hn_rx_ring = NULL; | ||||
sc->hn_rx_ring_cnt = 0; | sc->hn_rx_ring_cnt = 0; | ||||
sc->hn_rx_ring_inuse = 0; | sc->hn_rx_ring_inuse = 0; | ||||
if (sc->hn_rxbuf != NULL) { | |||||
hyperv_dmamem_free(&sc->hn_rxbuf_dma, sc->hn_rxbuf); | |||||
sc->hn_rxbuf = NULL; | |||||
} | |||||
} | } | ||||
static int | static int | ||||
hn_create_tx_ring(struct hn_softc *sc, int id) | hn_create_tx_ring(struct hn_softc *sc, int id) | ||||
{ | { | ||||
struct hn_tx_ring *txr = &sc->hn_tx_ring[id]; | struct hn_tx_ring *txr = &sc->hn_tx_ring[id]; | ||||
device_t dev = sc->hn_dev; | device_t dev = sc->hn_dev; | ||||
bus_dma_tag_t parent_dtag; | bus_dma_tag_t parent_dtag; | ||||
▲ Show 20 Lines • Show All 680 Lines • Show Last 20 Lines |