Fix an interrupt storm issue in vnet(4) mpi@ managed to trigger on my T5220,
authorstsp <stsp@openbsd.org>
Sat, 27 Jan 2018 13:44:03 +0000 (13:44 +0000)
committerstsp <stsp@openbsd.org>
Sat, 27 Jan 2018 13:44:03 +0000 (13:44 +0000)
similar to the issue fixed in vldcp(4) recently. For good measure also fix
it again in vldcp(4) in case the Rx channel is reset rather than goes down.

My T5220 has been running fine with this change.

ok kettenis@

sys/arch/sparc64/dev/vldcp.c
sys/arch/sparc64/dev/vnet.c

index 5aed7b2..470d1dc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vldcp.c,v 1.15 2018/01/17 15:52:34 stsp Exp $ */
+/*     $OpenBSD: vldcp.c,v 1.16 2018/01/27 13:44:03 stsp Exp $ */
 /*
  * Copyright (c) 2009, 2012 Mark Kettenis
  *
@@ -251,7 +251,7 @@ vldcp_rx_intr(void *arg)
                        if (rx_head == rx_tail)
                                break;
                        /* Discard and ack pending I/O. */
-                       DPRINTF(("setting rx qhead to %lld\n", rx_tail));
+                       DPRINTF(("setting rx qhead to %llx\n", rx_tail));
                        err = hv_ldc_rx_set_qhead(lc->lc_id, rx_tail);
                        if (err == H_EOK)
                                break;
@@ -262,6 +262,14 @@ vldcp_rx_intr(void *arg)
                        break;
                case LDC_CHANNEL_RESET:
                        DPRINTF(("%s: Rx link reset\n", __func__));
+                       if (rx_head == rx_tail)
+                               break;
+                       /* Discard and ack pending I/O. */
+                       DPRINTF(("setting rx qhead to %llx\n", rx_tail));
+                       err = hv_ldc_rx_set_qhead(lc->lc_id, rx_tail);
+                       if (err == H_EOK)
+                               break;
+                       printf("%s: hv_ldc_rx_set_qhead %d\n", __func__, err);
                        break;
                }
                lc->lc_rx_state = rx_state;
@@ -378,14 +386,14 @@ retry:
                return (EIO);
        }
 
+       DPRINTF(("rx head %llx, rx tail %llx, state %lld\n", rx_head, rx_tail, rx_state));
+
        if (rx_state != LDC_CHANNEL_UP) {
                splx(s);
                device_unref(&sc->sc_dv);
                return (EIO);
        }
 
-       DPRINTF(("rx head %llx, rx tail %llx\n", rx_head, rx_tail));
-
        if (rx_head == rx_tail) {
                cbus_intr_setenabled(sc->sc_bustag, sc->sc_rx_ino,
                    INTR_ENABLED);
index 4d1e96b..147caf1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vnet.c,v 1.59 2018/01/17 15:52:34 stsp Exp $  */
+/*     $OpenBSD: vnet.c,v 1.60 2018/01/27 13:44:03 stsp Exp $  */
 /*
  * Copyright (c) 2009, 2015 Mark Kettenis
  *
@@ -380,6 +380,14 @@ vnet_rx_intr(void *arg)
                        lc->lc_tx_seqid = 0;
                        lc->lc_state = 0;
                        lc->lc_reset(lc);
+                       if (rx_head == rx_tail)
+                               break;
+                       /* Discard and ack pending I/O. */
+                       DPRINTF(("setting rx qhead to %lld\n", rx_tail));
+                       err = hv_ldc_rx_set_qhead(lc->lc_id, rx_tail);
+                       if (err == H_EOK)
+                               break;
+                       printf("%s: hv_ldc_rx_set_qhead %d\n", __func__, err);
                        break;
                case LDC_CHANNEL_UP:
                        DPRINTF(("%s: Rx link up\n", __func__));
@@ -391,6 +399,14 @@ vnet_rx_intr(void *arg)
                        lc->lc_state = 0;
                        lc->lc_reset(lc);
                        timeout_add_msec(&sc->sc_handshake_to, 500);
+                       if (rx_head == rx_tail)
+                               break;
+                       /* Discard and ack pending I/O. */
+                       DPRINTF(("setting rx qhead to %lld\n", rx_tail));
+                       err = hv_ldc_rx_set_qhead(lc->lc_id, rx_tail);
+                       if (err == H_EOK)
+                               break;
+                       printf("%s: hv_ldc_rx_set_qhead %d\n", __func__, err);
                        break;
                }
                lc->lc_rx_state = rx_state;