Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
Show First 20 Lines • Show All 329 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_fixup_tx_data(struct hn_softc *); | static void hn_fixup_tx_data(struct hn_softc *); | ||||
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_link_taskfunc(void *, int); | static void hn_link_taskfunc(void *, int); | ||||
static void hn_netchg_init_taskfunc(void *, int); | |||||
static void hn_netchg_status_taskfunc(void *, int); | |||||
static void hn_suspend_mgmt_taskfunc(void *, int); | static void hn_suspend_mgmt_taskfunc(void *, int); | ||||
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_chim_size(struct hn_softc *, int); | static void hn_set_chim_size(struct hn_softc *, int); | ||||
static void hn_set_tso_maxsize(struct hn_softc *, int, int); | static void hn_set_tso_maxsize(struct hn_softc *, int, int); | ||||
static int hn_chan_attach(struct hn_softc *, struct vmbus_channel *); | static int hn_chan_attach(struct hn_softc *, struct vmbus_channel *); | ||||
static void hn_chan_detach(struct hn_softc *, struct vmbus_channel *); | static void hn_chan_detach(struct hn_softc *, struct vmbus_channel *); | ||||
Show All 9 Lines | |||||
static void hn_suspend_mgmt(struct hn_softc *); | static void hn_suspend_mgmt(struct hn_softc *); | ||||
static void hn_resume(struct hn_softc *); | static void hn_resume(struct hn_softc *); | ||||
static void hn_resume_data(struct hn_softc *); | static void hn_resume_data(struct hn_softc *); | ||||
static void hn_resume_mgmt(struct hn_softc *); | static void hn_resume_mgmt(struct hn_softc *); | ||||
static void hn_rx_drain(struct vmbus_channel *); | static void hn_rx_drain(struct vmbus_channel *); | ||||
static void hn_tx_resume(struct hn_softc *, int); | static void hn_tx_resume(struct hn_softc *, int); | ||||
static void hn_tx_ring_qflush(struct hn_tx_ring *); | static void hn_tx_ring_qflush(struct hn_tx_ring *); | ||||
static int netvsc_detach(device_t dev); | static int netvsc_detach(device_t dev); | ||||
static void hn_link_status(struct hn_softc *); | |||||
static void hn_nvs_handle_notify(struct hn_softc *sc, | static void hn_nvs_handle_notify(struct hn_softc *sc, | ||||
const struct vmbus_chanpkt_hdr *pkt); | const struct vmbus_chanpkt_hdr *pkt); | ||||
static void hn_nvs_handle_comp(struct hn_softc *sc, struct vmbus_channel *chan, | static void hn_nvs_handle_comp(struct hn_softc *sc, struct vmbus_channel *chan, | ||||
const struct vmbus_chanpkt_hdr *pkt); | const struct vmbus_chanpkt_hdr *pkt); | ||||
static void hn_nvs_handle_rxbuf(struct hn_softc *sc, struct hn_rx_ring *rxr, | static void hn_nvs_handle_rxbuf(struct hn_softc *sc, struct hn_rx_ring *rxr, | ||||
struct vmbus_channel *chan, | struct vmbus_channel *chan, | ||||
const struct vmbus_chanpkt_hdr *pkthdr); | const struct vmbus_chanpkt_hdr *pkthdr); | ||||
▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
hn_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) | hn_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) | ||||
{ | { | ||||
struct hn_softc *sc = ifp->if_softc; | struct hn_softc *sc = ifp->if_softc; | ||||
ifmr->ifm_status = IFM_AVALID; | ifmr->ifm_status = IFM_AVALID; | ||||
ifmr->ifm_active = IFM_ETHER; | ifmr->ifm_active = IFM_ETHER; | ||||
if (!sc->hn_carrier) { | if ((sc->hn_link_flags & HN_LINK_FLAG_LINKUP) == 0) { | ||||
ifmr->ifm_active |= IFM_NONE; | ifmr->ifm_active |= IFM_NONE; | ||||
return; | return; | ||||
} | } | ||||
ifmr->ifm_status |= IFM_ACTIVE; | ifmr->ifm_status |= IFM_ACTIVE; | ||||
ifmr->ifm_active |= IFM_10G_T | IFM_FDX; | ifmr->ifm_active |= IFM_10G_T | IFM_FDX; | ||||
} | } | ||||
/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */ | /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */ | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | netvsc_attach(device_t dev) | ||||
/* | /* | ||||
* Setup taskqueue for mangement tasks, e.g. link status. | * Setup taskqueue for mangement tasks, e.g. link status. | ||||
*/ | */ | ||||
sc->hn_mgmt_taskq0 = taskqueue_create("hn_mgmt", M_WAITOK, | sc->hn_mgmt_taskq0 = taskqueue_create("hn_mgmt", M_WAITOK, | ||||
taskqueue_thread_enqueue, &sc->hn_mgmt_taskq0); | taskqueue_thread_enqueue, &sc->hn_mgmt_taskq0); | ||||
taskqueue_start_threads(&sc->hn_mgmt_taskq0, 1, PI_NET, "%s mgmt", | taskqueue_start_threads(&sc->hn_mgmt_taskq0, 1, PI_NET, "%s mgmt", | ||||
device_get_nameunit(dev)); | device_get_nameunit(dev)); | ||||
TASK_INIT(&sc->hn_link_task, 0, hn_link_taskfunc, sc); | TASK_INIT(&sc->hn_link_task, 0, hn_link_taskfunc, sc); | ||||
TASK_INIT(&sc->hn_netchg_init, 0, hn_netchg_init_taskfunc, sc); | |||||
TIMEOUT_TASK_INIT(sc->hn_mgmt_taskq0, &sc->hn_netchg_status, 0, | |||||
hn_netchg_status_taskfunc, sc); | |||||
/* | /* | ||||
* Allocate ifnet and setup its name earlier, so that if_printf | * Allocate ifnet and setup its name earlier, so that if_printf | ||||
* can be used by functions, which will be called after | * can be used by functions, which will be called after | ||||
* ether_ifattach(). | * ether_ifattach(). | ||||
*/ | */ | ||||
ifp = sc->hn_ifp = if_alloc(IFT_ETHER); | ifp = sc->hn_ifp = if_alloc(IFT_ETHER); | ||||
ifp->if_softc = sc; | ifp->if_softc = sc; | ||||
▲ Show 20 Lines • Show All 229 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static int | static int | ||||
netvsc_shutdown(device_t dev) | netvsc_shutdown(device_t dev) | ||||
{ | { | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
hn_link_taskfunc(void *xsc, int pending __unused) | hn_link_status(struct hn_softc *sc) | ||||
{ | { | ||||
struct hn_softc *sc = xsc; | |||||
struct ifnet *ifp = sc->hn_ifp; | |||||
uint32_t link_status; | uint32_t link_status; | ||||
int error; | int error; | ||||
error = hn_rndis_get_linkstatus(sc, &link_status); | error = hn_rndis_get_linkstatus(sc, &link_status); | ||||
if (error) { | if (error) { | ||||
/* XXX what to do? */ | /* XXX what to do? */ | ||||
return; | return; | ||||
} | } | ||||
if (link_status == NDIS_MEDIA_STATE_CONNECTED) | if (link_status == NDIS_MEDIA_STATE_CONNECTED) | ||||
sc->hn_carrier = 1; | sc->hn_link_flags |= HN_LINK_FLAG_LINKUP; | ||||
else | else | ||||
sc->hn_carrier = 0; | sc->hn_link_flags &= ~HN_LINK_FLAG_LINKUP; | ||||
if_link_state_change(ifp, | if_link_state_change(sc->hn_ifp, | ||||
sc->hn_carrier ? LINK_STATE_UP : LINK_STATE_DOWN); | (sc->hn_link_flags & HN_LINK_FLAG_LINKUP) ? | ||||
LINK_STATE_UP : LINK_STATE_DOWN); | |||||
} | } | ||||
static void | |||||
hn_link_taskfunc(void *xsc, int pending __unused) | |||||
{ | |||||
struct hn_softc *sc = xsc; | |||||
if (sc->hn_link_flags & HN_LINK_FLAG_NETCHG) | |||||
return; | |||||
hn_link_status(sc); | |||||
} | |||||
static void | |||||
hn_netchg_init_taskfunc(void *xsc, int pending __unused) | |||||
{ | |||||
struct hn_softc *sc = xsc; | |||||
/* Prevent any link status checks from running. */ | |||||
sc->hn_link_flags |= HN_LINK_FLAG_NETCHG; | |||||
/* | |||||
* Fake up a [link down --> link up] state change; 5 seconds | |||||
* delay is used, which closely simulates miibus reaction | |||||
* upon link down event. | |||||
*/ | |||||
sc->hn_link_flags &= ~HN_LINK_FLAG_LINKUP; | |||||
if_link_state_change(sc->hn_ifp, LINK_STATE_DOWN); | |||||
taskqueue_enqueue_timeout(sc->hn_mgmt_taskq0, | |||||
&sc->hn_netchg_status, 5 * hz); | |||||
} | |||||
static void | |||||
hn_netchg_status_taskfunc(void *xsc, int pending __unused) | |||||
{ | |||||
struct hn_softc *sc = xsc; | |||||
/* Re-allow link status checks. */ | |||||
sc->hn_link_flags &= ~HN_LINK_FLAG_NETCHG; | |||||
hn_link_status(sc); | |||||
} | |||||
void | void | ||||
hn_link_status_update(struct hn_softc *sc) | hn_link_status_update(struct hn_softc *sc) | ||||
{ | { | ||||
if (sc->hn_mgmt_taskq != NULL) | if (sc->hn_mgmt_taskq != NULL) | ||||
taskqueue_enqueue(sc->hn_mgmt_taskq, &sc->hn_link_task); | taskqueue_enqueue(sc->hn_mgmt_taskq, &sc->hn_link_task); | ||||
} | } | ||||
void | |||||
hn_network_change(struct hn_softc *sc) | |||||
{ | |||||
if (sc->hn_mgmt_taskq != NULL) | |||||
taskqueue_enqueue(sc->hn_mgmt_taskq, &sc->hn_netchg_init); | |||||
} | |||||
static __inline int | static __inline int | ||||
hn_txdesc_dmamap_load(struct hn_tx_ring *txr, struct hn_txdesc *txd, | hn_txdesc_dmamap_load(struct hn_tx_ring *txr, struct hn_txdesc *txd, | ||||
struct mbuf **m_head, bus_dma_segment_t *segs, int *nsegs) | struct mbuf **m_head, bus_dma_segment_t *segs, int *nsegs) | ||||
{ | { | ||||
struct mbuf *m = *m_head; | struct mbuf *m = *m_head; | ||||
int error; | int error; | ||||
error = bus_dmamap_load_mbuf_sg(txr->hn_tx_data_dtag, txd->data_dmap, | error = bus_dmamap_load_mbuf_sg(txr->hn_tx_data_dtag, txd->data_dmap, | ||||
▲ Show 20 Lines • Show All 2,866 Lines • ▼ Show 20 Lines | hn_suspend_mgmt(struct hn_softc *sc) | ||||
* through hn_mgmt_taskq. | * through hn_mgmt_taskq. | ||||
*/ | */ | ||||
TASK_INIT(&task, 0, hn_suspend_mgmt_taskfunc, sc); | TASK_INIT(&task, 0, hn_suspend_mgmt_taskfunc, sc); | ||||
vmbus_chan_run_task(sc->hn_prichan, &task); | vmbus_chan_run_task(sc->hn_prichan, &task); | ||||
/* | /* | ||||
* Make sure that all pending management tasks are completed. | * Make sure that all pending management tasks are completed. | ||||
*/ | */ | ||||
taskqueue_drain(sc->hn_mgmt_taskq0, &sc->hn_netchg_init); | |||||
taskqueue_drain_timeout(sc->hn_mgmt_taskq0, &sc->hn_netchg_status); | |||||
taskqueue_drain_all(sc->hn_mgmt_taskq0); | taskqueue_drain_all(sc->hn_mgmt_taskq0); | ||||
} | } | ||||
static void | static void | ||||
hn_suspend(struct hn_softc *sc) | hn_suspend(struct hn_softc *sc) | ||||
{ | { | ||||
if (sc->hn_ifp->if_drv_flags & IFF_DRV_RUNNING) | if (sc->hn_ifp->if_drv_flags & IFF_DRV_RUNNING) | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | hn_resume_data(struct hn_softc *sc) | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
hn_resume_mgmt(struct hn_softc *sc) | hn_resume_mgmt(struct hn_softc *sc) | ||||
{ | { | ||||
/* | /* | ||||
* Kick off link status check. | * Kick off network change detection, which will | ||||
* do link status check too. | |||||
*/ | */ | ||||
sc->hn_mgmt_taskq = sc->hn_mgmt_taskq0; | sc->hn_mgmt_taskq = sc->hn_mgmt_taskq0; | ||||
hn_link_status_update(sc); | hn_network_change(sc); | ||||
} | } | ||||
static void | static void | ||||
hn_resume(struct hn_softc *sc) | hn_resume(struct hn_softc *sc) | ||||
{ | { | ||||
if (sc->hn_ifp->if_drv_flags & IFF_DRV_RUNNING) | if (sc->hn_ifp->if_drv_flags & IFF_DRV_RUNNING) | ||||
hn_resume_data(sc); | hn_resume_data(sc); | ||||
▲ Show 20 Lines • Show All 249 Lines • Show Last 20 Lines |