Changeset View
Changeset View
Standalone View
Standalone View
head/usr.sbin/bhyve/pci_virtio_net.c
Show First 20 Lines • Show All 144 Lines • ▼ Show 20 Lines | struct pci_vtnet_softc { | ||||
struct vqueue_info vsc_queues[VTNET_MAXQ - 1]; | struct vqueue_info vsc_queues[VTNET_MAXQ - 1]; | ||||
pthread_mutex_t vsc_mtx; | pthread_mutex_t vsc_mtx; | ||||
struct mevent *vsc_mevp; | struct mevent *vsc_mevp; | ||||
int vsc_tapfd; | int vsc_tapfd; | ||||
struct nm_desc *vsc_nmd; | struct nm_desc *vsc_nmd; | ||||
int vsc_rx_ready; | int vsc_rx_ready; | ||||
volatile int resetting; /* set and checked outside lock */ | int resetting; /* protected by tx_mtx */ | ||||
uint64_t vsc_features; /* negotiated features */ | uint64_t vsc_features; /* negotiated features */ | ||||
struct virtio_net_config vsc_config; | struct virtio_net_config vsc_config; | ||||
pthread_mutex_t rx_mtx; | pthread_mutex_t rx_mtx; | ||||
int rx_in_progress; | |||||
int rx_vhdrlen; | int rx_vhdrlen; | ||||
int rx_merge; /* merged rx bufs in use */ | int rx_merge; /* merged rx bufs in use */ | ||||
pthread_t tx_tid; | pthread_t tx_tid; | ||||
pthread_mutex_t tx_mtx; | pthread_mutex_t tx_mtx; | ||||
pthread_cond_t tx_cond; | pthread_cond_t tx_cond; | ||||
int tx_in_progress; | int tx_in_progress; | ||||
Show All 15 Lines | static struct virtio_consts vtnet_vi_consts = { | ||||
pci_vtnet_reset, /* reset */ | pci_vtnet_reset, /* reset */ | ||||
NULL, /* device-wide qnotify -- not used */ | NULL, /* device-wide qnotify -- not used */ | ||||
pci_vtnet_cfgread, /* read PCI config */ | pci_vtnet_cfgread, /* read PCI config */ | ||||
pci_vtnet_cfgwrite, /* write PCI config */ | pci_vtnet_cfgwrite, /* write PCI config */ | ||||
pci_vtnet_neg_features, /* apply negotiated features */ | pci_vtnet_neg_features, /* apply negotiated features */ | ||||
VTNET_S_HOSTCAPS, /* our capabilities */ | VTNET_S_HOSTCAPS, /* our capabilities */ | ||||
}; | }; | ||||
/* | |||||
* If the transmit thread is active then stall until it is done. | |||||
*/ | |||||
static void | static void | ||||
pci_vtnet_txwait(struct pci_vtnet_softc *sc) | pci_vtnet_reset(void *vsc) | ||||
{ | { | ||||
struct pci_vtnet_softc *sc = vsc; | |||||
DPRINTF(("vtnet: device reset requested !\n")); | |||||
/* Acquire the RX lock to block RX processing. */ | |||||
pthread_mutex_lock(&sc->rx_mtx); | |||||
/* Set sc->resetting and give a chance to the TX thread to stop. */ | |||||
pthread_mutex_lock(&sc->tx_mtx); | pthread_mutex_lock(&sc->tx_mtx); | ||||
sc->resetting = 1; | |||||
while (sc->tx_in_progress) { | while (sc->tx_in_progress) { | ||||
pthread_mutex_unlock(&sc->tx_mtx); | pthread_mutex_unlock(&sc->tx_mtx); | ||||
usleep(10000); | usleep(10000); | ||||
pthread_mutex_lock(&sc->tx_mtx); | pthread_mutex_lock(&sc->tx_mtx); | ||||
} | } | ||||
pthread_mutex_unlock(&sc->tx_mtx); | |||||
} | |||||
/* | |||||
* If the receive thread is active then stall until it is done. | |||||
*/ | |||||
static void | |||||
pci_vtnet_rxwait(struct pci_vtnet_softc *sc) | |||||
{ | |||||
pthread_mutex_lock(&sc->rx_mtx); | |||||
while (sc->rx_in_progress) { | |||||
pthread_mutex_unlock(&sc->rx_mtx); | |||||
usleep(10000); | |||||
pthread_mutex_lock(&sc->rx_mtx); | |||||
} | |||||
pthread_mutex_unlock(&sc->rx_mtx); | |||||
} | |||||
static void | |||||
pci_vtnet_reset(void *vsc) | |||||
{ | |||||
struct pci_vtnet_softc *sc = vsc; | |||||
DPRINTF(("vtnet: device reset requested !\n")); | |||||
sc->resetting = 1; | |||||
/* | |||||
* Wait for the transmit and receive threads to finish their | |||||
* processing. | |||||
*/ | |||||
pci_vtnet_txwait(sc); | |||||
pci_vtnet_rxwait(sc); | |||||
sc->vsc_rx_ready = 0; | sc->vsc_rx_ready = 0; | ||||
sc->rx_merge = 1; | sc->rx_merge = 1; | ||||
sc->rx_vhdrlen = sizeof(struct virtio_net_rxhdr); | sc->rx_vhdrlen = sizeof(struct virtio_net_rxhdr); | ||||
/* now reset rings, MSI-X vectors, and negotiated capabilities */ | /* | ||||
* Now reset rings, MSI-X vectors, and negotiated capabilities. | |||||
* Do that with the TX lock held, since we need to reset | |||||
* sc->resetting. | |||||
*/ | |||||
vi_reset_dev(&sc->vsc_vs); | vi_reset_dev(&sc->vsc_vs); | ||||
sc->resetting = 0; | sc->resetting = 0; | ||||
pthread_mutex_unlock(&sc->tx_mtx); | |||||
pthread_mutex_unlock(&sc->rx_mtx); | |||||
} | } | ||||
/* | /* | ||||
* Called to send a buffer chain out to the tap device | * Called to send a buffer chain out to the tap device | ||||
*/ | */ | ||||
static void | static void | ||||
pci_vtnet_tap_tx(struct pci_vtnet_softc *sc, struct iovec *iov, int iovcnt, | pci_vtnet_tap_tx(struct pci_vtnet_softc *sc, struct iovec *iov, int iovcnt, | ||||
int len) | int len) | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | pci_vtnet_tap_rx(struct pci_vtnet_softc *sc) | ||||
/* | /* | ||||
* Should never be called without a valid tap fd | * Should never be called without a valid tap fd | ||||
*/ | */ | ||||
assert(sc->vsc_tapfd != -1); | assert(sc->vsc_tapfd != -1); | ||||
/* | /* | ||||
* But, will be called when the rx ring hasn't yet | * But, will be called when the rx ring hasn't yet | ||||
* been set up or the guest is resetting the device. | * been set up. | ||||
*/ | */ | ||||
if (!sc->vsc_rx_ready || sc->resetting) { | if (!sc->vsc_rx_ready) { | ||||
/* | /* | ||||
* Drop the packet and try later. | * Drop the packet and try later. | ||||
*/ | */ | ||||
(void) read(sc->vsc_tapfd, dummybuf, sizeof(dummybuf)); | (void) read(sc->vsc_tapfd, dummybuf, sizeof(dummybuf)); | ||||
return; | return; | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 178 Lines • ▼ Show 20 Lines | pci_vtnet_netmap_rx(struct pci_vtnet_softc *sc) | ||||
/* | /* | ||||
* Should never be called without a valid netmap descriptor | * Should never be called without a valid netmap descriptor | ||||
*/ | */ | ||||
assert(sc->vsc_nmd != NULL); | assert(sc->vsc_nmd != NULL); | ||||
/* | /* | ||||
* But, will be called when the rx ring hasn't yet | * But, will be called when the rx ring hasn't yet | ||||
* been set up or the guest is resetting the device. | * been set up. | ||||
*/ | */ | ||||
if (!sc->vsc_rx_ready || sc->resetting) { | if (!sc->vsc_rx_ready) { | ||||
/* | /* | ||||
* Drop the packet and try later. | * Drop the packet and try later. | ||||
*/ | */ | ||||
(void) nm_nextpkt(sc->vsc_nmd, (void *)dummybuf); | (void) nm_nextpkt(sc->vsc_nmd, (void *)dummybuf); | ||||
return; | return; | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static void | static void | ||||
pci_vtnet_rx_callback(int fd, enum ev_type type, void *param) | pci_vtnet_rx_callback(int fd, enum ev_type type, void *param) | ||||
{ | { | ||||
struct pci_vtnet_softc *sc = param; | struct pci_vtnet_softc *sc = param; | ||||
pthread_mutex_lock(&sc->rx_mtx); | pthread_mutex_lock(&sc->rx_mtx); | ||||
sc->rx_in_progress = 1; | |||||
sc->pci_vtnet_rx(sc); | sc->pci_vtnet_rx(sc); | ||||
sc->rx_in_progress = 0; | |||||
pthread_mutex_unlock(&sc->rx_mtx); | pthread_mutex_unlock(&sc->rx_mtx); | ||||
} | } | ||||
static void | static void | ||||
pci_vtnet_ping_rxq(void *vsc, struct vqueue_info *vq) | pci_vtnet_ping_rxq(void *vsc, struct vqueue_info *vq) | ||||
{ | { | ||||
struct pci_vtnet_softc *sc = vsc; | struct pci_vtnet_softc *sc = vsc; | ||||
▲ Show 20 Lines • Show All 308 Lines • ▼ Show 20 Lines | #endif | ||||
/* use BAR 0 to map config regs in IO space */ | /* use BAR 0 to map config regs in IO space */ | ||||
vi_set_io_bar(&sc->vsc_vs, 0); | vi_set_io_bar(&sc->vsc_vs, 0); | ||||
sc->resetting = 0; | sc->resetting = 0; | ||||
sc->rx_merge = 1; | sc->rx_merge = 1; | ||||
sc->rx_vhdrlen = sizeof(struct virtio_net_rxhdr); | sc->rx_vhdrlen = sizeof(struct virtio_net_rxhdr); | ||||
sc->rx_in_progress = 0; | |||||
pthread_mutex_init(&sc->rx_mtx, NULL); | pthread_mutex_init(&sc->rx_mtx, NULL); | ||||
/* | /* | ||||
* Initialize tx semaphore & spawn TX processing thread. | * Initialize tx semaphore & spawn TX processing thread. | ||||
* As of now, only one thread for TX desc processing is | * As of now, only one thread for TX desc processing is | ||||
* spawned. | * spawned. | ||||
*/ | */ | ||||
sc->tx_in_progress = 0; | sc->tx_in_progress = 0; | ||||
▲ Show 20 Lines • Show All 63 Lines • Show Last 20 Lines |