Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/hyperv/netvsc/if_hn.c
Show First 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | |||||
#include <sys/sockio.h> | #include <sys/sockio.h> | ||||
#include <sys/sx.h> | #include <sys/sx.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/taskqueue.h> | #include <sys/taskqueue.h> | ||||
#include <sys/buf_ring.h> | #include <sys/buf_ring.h> | ||||
#include <sys/eventhandler.h> | #include <sys/eventhandler.h> | ||||
#include <sys/epoch.h> | #include <sys/epoch.h> | ||||
#include <vm/vm.h> | |||||
#include <vm/vm_extern.h> | |||||
#include <vm/pmap.h> | |||||
#include <machine/atomic.h> | #include <machine/atomic.h> | ||||
#include <machine/in_cksum.h> | #include <machine/in_cksum.h> | ||||
#include <net/bpf.h> | #include <net/bpf.h> | ||||
#include <net/ethernet.h> | #include <net/ethernet.h> | ||||
#include <net/if.h> | #include <net/if.h> | ||||
#include <net/if_dl.h> | #include <net/if_dl.h> | ||||
#include <net/if_media.h> | #include <net/if_media.h> | ||||
▲ Show 20 Lines • Show All 4,883 Lines • ▼ Show 20 Lines | #endif | ||||
/* | /* | ||||
* Create RXBUF for reception. | * Create RXBUF for reception. | ||||
* | * | ||||
* NOTE: | * NOTE: | ||||
* - It is shared by all channels. | * - It is shared by all channels. | ||||
* - A large enough buffer is allocated, certain version of NVSes | * - A large enough buffer is allocated, certain version of NVSes | ||||
* may further limit the usable space. | * may further limit the usable space. | ||||
*/ | */ | ||||
sc->hn_rxbuf = hyperv_dmamem_alloc(bus_get_dma_tag(dev), | sc->hn_rxbuf = contigmalloc(HN_RXBUF_SIZE, M_DEVBUF, M_WAITOK | M_ZERO, | ||||
PAGE_SIZE, 0, HN_RXBUF_SIZE, &sc->hn_rxbuf_dma, | 0ul, ~0ul, PAGE_SIZE, 0); | ||||
BUS_DMA_WAITOK | BUS_DMA_ZERO); | |||||
if (sc->hn_rxbuf == NULL) { | if (sc->hn_rxbuf == NULL) { | ||||
device_printf(sc->hn_dev, "allocate rxbuf failed\n"); | device_printf(sc->hn_dev, "allocate rxbuf failed\n"); | ||||
return (ENOMEM); | 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; | ||||
Show All 13 Lines | #endif /* INET || INET6 */ | ||||
/* Create dev.hn.UNIT.rx sysctl tree */ | /* Create dev.hn.UNIT.rx sysctl tree */ | ||||
sc->hn_rx_sysctl_tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "rx", | sc->hn_rx_sysctl_tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "rx", | ||||
CTLFLAG_RD | CTLFLAG_MPSAFE, 0, ""); | CTLFLAG_RD | CTLFLAG_MPSAFE, 0, ""); | ||||
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]; | ||||
rxr->hn_br = hyperv_dmamem_alloc(bus_get_dma_tag(dev), | rxr->hn_br = contigmalloc(HN_TXBR_SIZE + HN_RXBR_SIZE, M_DEVBUF, | ||||
PAGE_SIZE, 0, HN_TXBR_SIZE + HN_RXBR_SIZE, | M_WAITOK | M_ZERO, 0ul, ~0ul, PAGE_SIZE, 0); | ||||
&rxr->hn_br_dma, BUS_DMA_WAITOK); | |||||
if (rxr->hn_br == NULL) { | if (rxr->hn_br == NULL) { | ||||
device_printf(dev, "allocate bufring failed\n"); | device_printf(dev, "allocate bufring failed\n"); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
if (hn_trust_hosttcp) | if (hn_trust_hosttcp) | ||||
rxr->hn_trust_hcsum |= HN_TRUST_HCSUM_TCP; | rxr->hn_trust_hcsum |= HN_TRUST_HCSUM_TCP; | ||||
if (hn_trust_hostudp) | if (hn_trust_hostudp) | ||||
▲ Show 20 Lines • Show All 136 Lines • ▼ Show 20 Lines | |||||
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) { | if (sc->hn_rxbuf != NULL) { | ||||
if ((sc->hn_flags & HN_FLAG_RXBUF_REF) == 0) | if ((sc->hn_flags & HN_FLAG_RXBUF_REF) == 0) | ||||
hyperv_dmamem_free(&sc->hn_rxbuf_dma, sc->hn_rxbuf); | contigfree(sc->hn_rxbuf, HN_RXBUF_SIZE, M_DEVBUF); | ||||
else | else | ||||
device_printf(sc->hn_dev, "RXBUF is referenced\n"); | device_printf(sc->hn_dev, "RXBUF is referenced\n"); | ||||
sc->hn_rxbuf = NULL; | 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 (rxr->hn_br == NULL) | if (rxr->hn_br == NULL) | ||||
continue; | continue; | ||||
if ((rxr->hn_rx_flags & HN_RX_FLAG_BR_REF) == 0) { | if ((rxr->hn_rx_flags & HN_RX_FLAG_BR_REF) == 0) { | ||||
hyperv_dmamem_free(&rxr->hn_br_dma, rxr->hn_br); | contigfree(rxr->hn_br, HN_TXBR_SIZE + HN_RXBR_SIZE, | ||||
M_DEVBUF); | |||||
} else { | } else { | ||||
device_printf(sc->hn_dev, | device_printf(sc->hn_dev, | ||||
"%dth channel bufring is referenced", i); | "%dth channel bufring is referenced", i); | ||||
} | } | ||||
rxr->hn_br = NULL; | rxr->hn_br = NULL; | ||||
#if defined(INET) || defined(INET6) | #if defined(INET) || defined(INET6) | ||||
tcp_lro_free(&rxr->hn_lro); | tcp_lro_free(&rxr->hn_lro); | ||||
▲ Show 20 Lines • Show All 288 Lines • ▼ Show 20 Lines | hn_create_tx_data(struct hn_softc *sc, int ring_cnt) | ||||
struct sysctl_ctx_list *ctx; | struct sysctl_ctx_list *ctx; | ||||
int i; | int i; | ||||
/* | /* | ||||
* Create TXBUF for chimney sending. | * Create TXBUF for chimney sending. | ||||
* | * | ||||
* NOTE: It is shared by all channels. | * NOTE: It is shared by all channels. | ||||
*/ | */ | ||||
sc->hn_chim = hyperv_dmamem_alloc(bus_get_dma_tag(sc->hn_dev), | sc->hn_chim = contigmalloc(HN_CHIM_SIZE, M_DEVBUF, M_WAITOK | M_ZERO, | ||||
PAGE_SIZE, 0, HN_CHIM_SIZE, &sc->hn_chim_dma, | 0ul, ~0ul, PAGE_SIZE, 0); | ||||
BUS_DMA_WAITOK | BUS_DMA_ZERO); | |||||
if (sc->hn_chim == NULL) { | if (sc->hn_chim == NULL) { | ||||
device_printf(sc->hn_dev, "allocate txbuf failed\n"); | device_printf(sc->hn_dev, "allocate txbuf failed\n"); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
schakrabarti_microsoft.com: where is check for contigmalloc() failure? Missing in all the places | |||||
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_DEVBUF, M_WAITOK | M_ZERO); | M_DEVBUF, M_WAITOK | M_ZERO); | ||||
ctx = device_get_sysctl_ctx(sc->hn_dev); | ctx = device_get_sysctl_ctx(sc->hn_dev); | ||||
▲ Show 20 Lines • Show All 175 Lines • ▼ Show 20 Lines | |||||
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) { | if (sc->hn_chim != NULL) { | ||||
if ((sc->hn_flags & HN_FLAG_CHIM_REF) == 0) { | if ((sc->hn_flags & HN_FLAG_CHIM_REF) == 0) { | ||||
hyperv_dmamem_free(&sc->hn_chim_dma, sc->hn_chim); | contigfree(sc->hn_chim, HN_CHIM_SIZE, M_DEVBUF); | ||||
} else { | } else { | ||||
device_printf(sc->hn_dev, | device_printf(sc->hn_dev, | ||||
"chimney sending buffer is referenced"); | "chimney sending buffer is referenced"); | ||||
} | } | ||||
sc->hn_chim = NULL; | sc->hn_chim = NULL; | ||||
} | } | ||||
if (sc->hn_tx_ring_cnt == 0) | if (sc->hn_tx_ring_cnt == 0) | ||||
▲ Show 20 Lines • Show All 557 Lines • ▼ Show 20 Lines | hn_chan_attach(struct hn_softc *sc, struct vmbus_channel *chan) | ||||
/* Bind this channel to a proper CPU. */ | /* Bind this channel to a proper CPU. */ | ||||
vmbus_chan_cpu_set(chan, HN_RING_IDX2CPU(sc, idx)); | vmbus_chan_cpu_set(chan, HN_RING_IDX2CPU(sc, idx)); | ||||
/* | /* | ||||
* Open this channel | * Open this channel | ||||
*/ | */ | ||||
cbr.cbr = rxr->hn_br; | cbr.cbr = rxr->hn_br; | ||||
cbr.cbr_paddr = rxr->hn_br_dma.hv_paddr; | cbr.cbr_paddr = pmap_kextract((vm_offset_t)rxr->hn_br); | ||||
cbr.cbr_txsz = HN_TXBR_SIZE; | cbr.cbr_txsz = HN_TXBR_SIZE; | ||||
cbr.cbr_rxsz = HN_RXBR_SIZE; | cbr.cbr_rxsz = HN_RXBR_SIZE; | ||||
error = vmbus_chan_open_br(chan, &cbr, NULL, 0, hn_chan_callback, rxr); | error = vmbus_chan_open_br(chan, &cbr, NULL, 0, hn_chan_callback, rxr); | ||||
if (error) { | if (error) { | ||||
if (error == EISCONN) { | if (error == EISCONN) { | ||||
if_printf(sc->hn_ifp, "bufring is connected after " | if_printf(sc->hn_ifp, "bufring is connected after " | ||||
"chan%u open failure\n", vmbus_chan_id(chan)); | "chan%u open failure\n", vmbus_chan_id(chan)); | ||||
rxr->hn_rx_flags |= HN_RX_FLAG_BR_REF; | rxr->hn_rx_flags |= HN_RX_FLAG_BR_REF; | ||||
▲ Show 20 Lines • Show All 1,447 Lines • Show Last 20 Lines |
where is check for contigmalloc() failure? Missing in all the places