diff options
author | nwhitehorn <nwhitehorn@FreeBSD.org> | 2015-03-12 17:01:30 +0000 |
---|---|---|
committer | nwhitehorn <nwhitehorn@FreeBSD.org> | 2015-03-12 17:01:30 +0000 |
commit | 431cf92001509037ebe29bb3def0b68cb763b1ba (patch) | |
tree | 1c7624eb6d9a2089749511cb4bf36b98393c22b9 /sys/powerpc/pseries | |
parent | 397e76aa8d4fa9ffa0e77ec4fd3fbd63f1e96fbd (diff) | |
download | FreeBSD-src-431cf92001509037ebe29bb3def0b68cb763b1ba.zip FreeBSD-src-431cf92001509037ebe29bb3def0b68cb763b1ba.tar.gz |
The H_VIO_SIGNAL hypercall only enables interrupts for future received
packets and does not schedule interrupts for any packets currently
enqueued. Close two races where enqueued packets may not ever trigger
interrupts. The first of these, at adapter initialization time, was
especially severe since a rush of enqueued packets could actually fill
the receive buffer completely, stalling the interface forever.
MFC after: 2 weeks
Diffstat (limited to 'sys/powerpc/pseries')
-rw-r--r-- | sys/powerpc/pseries/phyp_llan.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/sys/powerpc/pseries/phyp_llan.c b/sys/powerpc/pseries/phyp_llan.c index 0b25f39..26dbcc0 100644 --- a/sys/powerpc/pseries/phyp_llan.c +++ b/sys/powerpc/pseries/phyp_llan.c @@ -273,6 +273,9 @@ llan_init(void *xsc) sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; mtx_unlock(&sc->io_lock); + + /* Check for pending receives scheduled before interrupt enable */ + llan_intr(sc); } static int @@ -335,6 +338,7 @@ llan_intr(void *xsc) struct mbuf *m; mtx_lock(&sc->io_lock); +restart: phyp_hcall(H_VIO_SIGNAL, sc->unit, 0); while ((sc->rx_buf[sc->rx_dma_slot].control >> 7) == sc->rx_valid_val) { @@ -369,6 +373,15 @@ llan_intr(void *xsc) } phyp_hcall(H_VIO_SIGNAL, sc->unit, 1); + + /* + * H_VIO_SIGNAL enables interrupts for future packets only. + * Make sure none were queued between the end of the loop and the + * enable interrupts call. + */ + if ((sc->rx_buf[sc->rx_dma_slot].control >> 7) == sc->rx_valid_val) + goto restart; + mtx_unlock(&sc->io_lock); } |