Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
Show First 20 Lines • Show All 322 Lines • ▼ Show 20 Lines | |||||
static void hn_start_txeof(struct hn_tx_ring *); | static void hn_start_txeof(struct hn_tx_ring *); | ||||
static int hn_ifmedia_upd(struct ifnet *ifp); | static int hn_ifmedia_upd(struct ifnet *ifp); | ||||
static void hn_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); | static void hn_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); | ||||
#if __FreeBSD_version >= 1100099 | #if __FreeBSD_version >= 1100099 | ||||
static int hn_lro_lenlim_sysctl(SYSCTL_HANDLER_ARGS); | static int hn_lro_lenlim_sysctl(SYSCTL_HANDLER_ARGS); | ||||
static int hn_lro_ackcnt_sysctl(SYSCTL_HANDLER_ARGS); | static int hn_lro_ackcnt_sysctl(SYSCTL_HANDLER_ARGS); | ||||
#endif | #endif | ||||
static int hn_trust_hcsum_sysctl(SYSCTL_HANDLER_ARGS); | static int hn_trust_hcsum_sysctl(SYSCTL_HANDLER_ARGS); | ||||
static int hn_tx_chimney_size_sysctl(SYSCTL_HANDLER_ARGS); | static int hn_chim_size_sysctl(SYSCTL_HANDLER_ARGS); | ||||
static int hn_rx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS); | static int hn_rx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS); | ||||
static int hn_rx_stat_u64_sysctl(SYSCTL_HANDLER_ARGS); | static int hn_rx_stat_u64_sysctl(SYSCTL_HANDLER_ARGS); | ||||
static int hn_tx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS); | static int hn_tx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS); | ||||
static int hn_tx_conf_int_sysctl(SYSCTL_HANDLER_ARGS); | static int hn_tx_conf_int_sysctl(SYSCTL_HANDLER_ARGS); | ||||
static int hn_check_iplen(const struct mbuf *, int); | static int hn_check_iplen(const struct mbuf *, int); | ||||
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 int 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_chim_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 *); | ||||
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 *); | ||||
▲ Show 20 Lines • Show All 245 Lines • ▼ Show 20 Lines | #endif | ||||
ether_ifattach(ifp, device_info.mac_addr); | ether_ifattach(ifp, device_info.mac_addr); | ||||
#if __FreeBSD_version >= 1100045 | #if __FreeBSD_version >= 1100045 | ||||
if_printf(ifp, "TSO: %u/%u/%u\n", ifp->if_hw_tsomax, | if_printf(ifp, "TSO: %u/%u/%u\n", ifp->if_hw_tsomax, | ||||
ifp->if_hw_tsomaxsegcount, ifp->if_hw_tsomaxsegsize); | ifp->if_hw_tsomaxsegcount, ifp->if_hw_tsomaxsegsize); | ||||
#endif | #endif | ||||
sc->hn_tx_chimney_max = sc->net_dev->send_section_size; | hn_set_chim_size(sc, sc->hn_chim_szmax); | ||||
hn_set_tx_chimney_size(sc, sc->hn_tx_chimney_max); | |||||
if (hn_tx_chimney_size > 0 && | if (hn_tx_chimney_size > 0 && | ||||
hn_tx_chimney_size < sc->hn_tx_chimney_max) | hn_tx_chimney_size < sc->hn_chim_szmax) | ||||
hn_set_tx_chimney_size(sc, hn_tx_chimney_size); | hn_set_chim_size(sc, hn_tx_chimney_size); | ||||
SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), | SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), | ||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, | SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, | ||||
"nvs_version", CTLFLAG_RD, &sc->hn_nvs_ver, 0, "NVS version"); | "nvs_version", CTLFLAG_RD, &sc->hn_nvs_ver, 0, "NVS version"); | ||||
return (0); | return (0); | ||||
failed: | failed: | ||||
hn_destroy_tx_data(sc); | hn_destroy_tx_data(sc); | ||||
▲ Show 20 Lines • Show All 169 Lines • ▼ Show 20 Lines | |||||
static __inline void | static __inline void | ||||
hn_txeof(struct hn_tx_ring *txr) | hn_txeof(struct hn_tx_ring *txr) | ||||
{ | { | ||||
txr->hn_has_txeof = 0; | txr->hn_has_txeof = 0; | ||||
txr->hn_txeof(txr); | txr->hn_txeof(txr); | ||||
} | } | ||||
static void | static void | ||||
hn_tx_done(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev, | hn_tx_done(struct hn_send_ctx *sndc, struct hn_softc *sc, | ||||
struct vmbus_channel *chan, const void *data __unused, int dlen __unused) | struct vmbus_channel *chan, const void *data __unused, int dlen __unused) | ||||
{ | { | ||||
struct hn_txdesc *txd = sndc->hn_cbarg; | struct hn_txdesc *txd = sndc->hn_cbarg; | ||||
struct hn_tx_ring *txr; | struct hn_tx_ring *txr; | ||||
if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID) | if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID) | ||||
hn_chim_free(net_dev, sndc->hn_chim_idx); | hn_chim_free(sc, sndc->hn_chim_idx); | ||||
txr = txd->txr; | txr = txd->txr; | ||||
KASSERT(txr->hn_chan == chan, | KASSERT(txr->hn_chan == chan, | ||||
("channel mismatch, on chan%u, should be chan%u", | ("channel mismatch, on chan%u, should be chan%u", | ||||
vmbus_chan_subidx(chan), vmbus_chan_subidx(txr->hn_chan))); | vmbus_chan_subidx(chan), vmbus_chan_subidx(txr->hn_chan))); | ||||
txr->hn_has_txeof = 1; | txr->hn_has_txeof = 1; | ||||
hn_txdesc_put(txr, txd); | hn_txdesc_put(txr, txd); | ||||
▲ Show 20 Lines • Show All 166 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
rndis_mesg->msg_len = tot_data_buf_len + rndis_msg_size; | rndis_mesg->msg_len = tot_data_buf_len + rndis_msg_size; | ||||
tot_data_buf_len = rndis_mesg->msg_len; | tot_data_buf_len = rndis_mesg->msg_len; | ||||
/* | /* | ||||
* Chimney send, if the packet could fit into one chimney buffer. | * Chimney send, if the packet could fit into one chimney buffer. | ||||
*/ | */ | ||||
if (tot_data_buf_len < txr->hn_tx_chimney_size) { | if (tot_data_buf_len < txr->hn_chim_size) { | ||||
netvsc_dev *net_dev = txr->hn_sc->net_dev; | |||||
txr->hn_tx_chimney_tried++; | txr->hn_tx_chimney_tried++; | ||||
send_buf_section_idx = | send_buf_section_idx = hn_chim_alloc(txr->hn_sc); | ||||
hv_nv_get_next_send_section(net_dev); | |||||
if (send_buf_section_idx != HN_NVS_CHIM_IDX_INVALID) { | if (send_buf_section_idx != HN_NVS_CHIM_IDX_INVALID) { | ||||
uint8_t *dest = ((uint8_t *)net_dev->send_buf + | uint8_t *dest = txr->hn_sc->hn_chim + | ||||
(send_buf_section_idx * | (send_buf_section_idx * txr->hn_sc->hn_chim_szmax); | ||||
net_dev->send_section_size)); | |||||
memcpy(dest, rndis_mesg, rndis_msg_size); | memcpy(dest, rndis_mesg, rndis_msg_size); | ||||
dest += rndis_msg_size; | dest += rndis_msg_size; | ||||
m_copydata(m_head, 0, m_head->m_pkthdr.len, dest); | m_copydata(m_head, 0, m_head->m_pkthdr.len, dest); | ||||
send_buf_section_size = tot_data_buf_len; | send_buf_section_size = tot_data_buf_len; | ||||
txr->hn_gpa_cnt = 0; | txr->hn_gpa_cnt = 0; | ||||
txr->hn_tx_chimney++; | txr->hn_tx_chimney++; | ||||
▲ Show 20 Lines • Show All 605 Lines • ▼ Show 20 Lines | if (sc->hn_rx_ring_inuse > 1) { | ||||
} | } | ||||
for (r = 1; r < sc->hn_tx_ring_cnt; ++r) { | for (r = 1; r < sc->hn_tx_ring_cnt; ++r) { | ||||
sc->hn_tx_ring[r].hn_tx_flags &= | sc->hn_tx_ring[r].hn_tx_flags &= | ||||
~HN_TX_FLAG_ATTACHED; | ~HN_TX_FLAG_ATTACHED; | ||||
} | } | ||||
hn_subchan_setup(sc); | hn_subchan_setup(sc); | ||||
} | } | ||||
sc->hn_tx_chimney_max = sc->net_dev->send_section_size; | if (sc->hn_tx_ring[0].hn_chim_size > sc->hn_chim_szmax) | ||||
if (sc->hn_tx_ring[0].hn_tx_chimney_size > | hn_set_chim_size(sc, sc->hn_chim_szmax); | ||||
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); | ||||
sc->temp_unusable = FALSE; | sc->temp_unusable = FALSE; | ||||
NV_UNLOCK(sc); | NV_UNLOCK(sc); | ||||
break; | break; | ||||
case SIOCSIFFLAGS: | case SIOCSIFFLAGS: | ||||
▲ Show 20 Lines • Show All 347 Lines • ▼ Show 20 Lines | for (i = 0; i < sc->hn_rx_ring_inuse; ++i) { | ||||
else | else | ||||
rxr->hn_trust_hcsum &= ~hcsum; | rxr->hn_trust_hcsum &= ~hcsum; | ||||
} | } | ||||
NV_UNLOCK(sc); | NV_UNLOCK(sc); | ||||
return 0; | return 0; | ||||
} | } | ||||
static int | static int | ||||
hn_tx_chimney_size_sysctl(SYSCTL_HANDLER_ARGS) | hn_chim_size_sysctl(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct hn_softc *sc = arg1; | struct hn_softc *sc = arg1; | ||||
int chimney_size, error; | int chim_size, error; | ||||
chimney_size = sc->hn_tx_ring[0].hn_tx_chimney_size; | chim_size = sc->hn_tx_ring[0].hn_chim_size; | ||||
error = sysctl_handle_int(oidp, &chimney_size, 0, req); | error = sysctl_handle_int(oidp, &chim_size, 0, req); | ||||
if (error || req->newptr == NULL) | if (error || req->newptr == NULL) | ||||
return error; | return error; | ||||
if (chimney_size > sc->hn_tx_chimney_max || chimney_size <= 0) | if (chim_size > sc->hn_chim_szmax || chim_size <= 0) | ||||
return EINVAL; | return EINVAL; | ||||
hn_set_tx_chimney_size(sc, chimney_size); | hn_set_chim_size(sc, chim_size); | ||||
return 0; | return 0; | ||||
} | } | ||||
static int | static int | ||||
hn_rx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS) | hn_rx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct hn_softc *sc = arg1; | struct hn_softc *sc = arg1; | ||||
int ofs = arg2, i, error; | int ofs = arg2, i, error; | ||||
▲ Show 20 Lines • Show All 345 Lines • ▼ Show 20 Lines | #endif | ||||
return (0); | 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_rxbuf != NULL) { | |||||
hyperv_dmamem_free(&sc->hn_rxbuf_dma, sc->hn_rxbuf); | |||||
sc->hn_rxbuf = NULL; | |||||
} | |||||
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; | ||||
int error, i; | int error, i; | ||||
▲ Show 20 Lines • Show All 242 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
hn_create_tx_data(struct hn_softc *sc, int ring_cnt) | hn_create_tx_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; | ||||
int i; | int i; | ||||
/* | |||||
* Create TXBUF for chimney sending. | |||||
* | |||||
* NOTE: It is shared by all channels. | |||||
*/ | |||||
sc->hn_chim = hyperv_dmamem_alloc(bus_get_dma_tag(sc->hn_dev), | |||||
PAGE_SIZE, 0, NETVSC_SEND_BUFFER_SIZE, &sc->hn_chim_dma, | |||||
BUS_DMA_WAITOK | BUS_DMA_ZERO); | |||||
if (sc->hn_chim == NULL) { | |||||
device_printf(sc->hn_dev, "allocate txbuf failed\n"); | |||||
return (ENOMEM); | |||||
} | |||||
sc->hn_tx_ring_cnt = ring_cnt; | sc->hn_tx_ring_cnt = ring_cnt; | ||||
sc->hn_tx_ring_inuse = sc->hn_tx_ring_cnt; | sc->hn_tx_ring_inuse = sc->hn_tx_ring_cnt; | ||||
sc->hn_tx_ring = malloc(sizeof(struct hn_tx_ring) * sc->hn_tx_ring_cnt, | sc->hn_tx_ring = malloc(sizeof(struct hn_tx_ring) * sc->hn_tx_ring_cnt, | ||||
M_NETVSC, M_WAITOK | M_ZERO); | M_NETVSC, M_WAITOK | M_ZERO); | ||||
ctx = device_get_sysctl_ctx(sc->hn_dev); | ctx = device_get_sysctl_ctx(sc->hn_dev); | ||||
child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->hn_dev)); | child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->hn_dev)); | ||||
Show All 33 Lines | hn_create_tx_data(struct hn_softc *sc, int ring_cnt) | ||||
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "tx_chimney_tried", | SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "tx_chimney_tried", | ||||
CTLTYPE_ULONG | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, | CTLTYPE_ULONG | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, | ||||
__offsetof(struct hn_tx_ring, hn_tx_chimney_tried), | __offsetof(struct hn_tx_ring, hn_tx_chimney_tried), | ||||
hn_tx_stat_ulong_sysctl, "LU", "# of chimney send tries"); | hn_tx_stat_ulong_sysctl, "LU", "# of chimney send tries"); | ||||
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "txdesc_cnt", | SYSCTL_ADD_INT(ctx, child, OID_AUTO, "txdesc_cnt", | ||||
CTLFLAG_RD, &sc->hn_tx_ring[0].hn_txdesc_cnt, 0, | CTLFLAG_RD, &sc->hn_tx_ring[0].hn_txdesc_cnt, 0, | ||||
"# of total TX descs"); | "# of total TX descs"); | ||||
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "tx_chimney_max", | SYSCTL_ADD_INT(ctx, child, OID_AUTO, "tx_chimney_max", | ||||
CTLFLAG_RD, &sc->hn_tx_chimney_max, 0, | CTLFLAG_RD, &sc->hn_chim_szmax, 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 | CTLFLAG_MPSAFE, sc, 0, | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, 0, | ||||
hn_tx_chimney_size_sysctl, | hn_chim_size_sysctl, "I", "Chimney send packet size limit"); | ||||
"I", "Chimney send packet size limit"); | |||||
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "direct_tx_size", | SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "direct_tx_size", | ||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, | ||||
__offsetof(struct hn_tx_ring, hn_direct_tx_size), | __offsetof(struct hn_tx_ring, hn_direct_tx_size), | ||||
hn_tx_conf_int_sysctl, "I", | hn_tx_conf_int_sysctl, "I", | ||||
"Size of the packet for direct transmission"); | "Size of the packet for direct transmission"); | ||||
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "sched_tx", | SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "sched_tx", | ||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, | ||||
__offsetof(struct hn_tx_ring, hn_sched_tx), | __offsetof(struct hn_tx_ring, hn_sched_tx), | ||||
hn_tx_conf_int_sysctl, "I", | hn_tx_conf_int_sysctl, "I", | ||||
"Always schedule transmission " | "Always schedule transmission " | ||||
"instead of doing direct transmission"); | "instead of doing direct transmission"); | ||||
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "tx_ring_cnt", | SYSCTL_ADD_INT(ctx, child, OID_AUTO, "tx_ring_cnt", | ||||
CTLFLAG_RD, &sc->hn_tx_ring_cnt, 0, "# created TX rings"); | CTLFLAG_RD, &sc->hn_tx_ring_cnt, 0, "# created TX rings"); | ||||
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "tx_ring_inuse", | SYSCTL_ADD_INT(ctx, child, OID_AUTO, "tx_ring_inuse", | ||||
CTLFLAG_RD, &sc->hn_tx_ring_inuse, 0, "# used TX rings"); | CTLFLAG_RD, &sc->hn_tx_ring_inuse, 0, "# used TX rings"); | ||||
return 0; | return 0; | ||||
} | } | ||||
static void | static void | ||||
hn_set_tx_chimney_size(struct hn_softc *sc, int chimney_size) | hn_set_chim_size(struct hn_softc *sc, int chim_size) | ||||
{ | { | ||||
int i; | int i; | ||||
NV_LOCK(sc); | NV_LOCK(sc); | ||||
for (i = 0; i < sc->hn_tx_ring_inuse; ++i) | for (i = 0; i < sc->hn_tx_ring_inuse; ++i) | ||||
sc->hn_tx_ring[i].hn_tx_chimney_size = chimney_size; | sc->hn_tx_ring[i].hn_chim_size = chim_size; | ||||
NV_UNLOCK(sc); | NV_UNLOCK(sc); | ||||
} | } | ||||
static void | static void | ||||
hn_destroy_tx_data(struct hn_softc *sc) | hn_destroy_tx_data(struct hn_softc *sc) | ||||
{ | { | ||||
int i; | int i; | ||||
if (sc->hn_chim != NULL) { | |||||
hyperv_dmamem_free(&sc->hn_chim_dma, sc->hn_chim); | |||||
sc->hn_chim = NULL; | |||||
} | |||||
if (sc->hn_tx_ring_cnt == 0) | if (sc->hn_tx_ring_cnt == 0) | ||||
return; | return; | ||||
for (i = 0; i < sc->hn_tx_ring_cnt; ++i) | for (i = 0; i < sc->hn_tx_ring_cnt; ++i) | ||||
hn_destroy_tx_ring(&sc->hn_tx_ring[i]); | hn_destroy_tx_ring(&sc->hn_tx_ring[i]); | ||||
free(sc->hn_tx_ring, M_NETVSC); | free(sc->hn_tx_ring, M_NETVSC); | ||||
▲ Show 20 Lines • Show All 332 Lines • Show Last 20 Lines |