summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/pseries
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2015-03-12 17:01:30 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2015-03-12 17:01:30 +0000
commit431cf92001509037ebe29bb3def0b68cb763b1ba (patch)
tree1c7624eb6d9a2089749511cb4bf36b98393c22b9 /sys/powerpc/pseries
parent397e76aa8d4fa9ffa0e77ec4fd3fbd63f1e96fbd (diff)
downloadFreeBSD-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.c13
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);
}
OpenPOWER on IntegriCloud