From a747fd2cf184031fedccff9fc0e7fb31d7d5cab8 Mon Sep 17 00:00:00 2001
From: Roger Pau Monne <roger.pau@citrix.com>
Date: Thu, 19 Jun 2014 13:06:05 +0200
Subject: [PATCH v5 29/29] xen: fix netback disconnect issues

Netback disconnect performed in xnb_shutdown was not taking the
required lock when modifying xnb->carrier, which is guarded by the
rx_lock. Also, make sure the xnb_disconnect disconnect is performed
before shutting down the interface. This fix prevents the following
panic:

Kernel page fault with the following non-sleepable locks held:
exclusive sleep mutex if_bridge (if_bridge) r = 0 (0xfffff80006306c18) locked @ /usr/src/sys/modules/if_bridge/../../net/if_bridge.c:2260
KDB: stack backtrace:
X_db_symbol_values() at X_db_symbol_values+0x10b/frame 0xfffffe0000213490
kdb_backtrace() at kdb_backtrace+0x39/frame 0xfffffe0000213540
witness_warn() at witness_warn+0x4a8/frame 0xfffffe0000213600
trap() at trap+0xc9d/frame 0xfffffe00002136a0
trap() at trap+0x669/frame 0xfffffe00002138b0
calltrap() at calltrap+0x8/frame 0xfffffe00002138b0
--- trap 0xc, rip = 0xffffffff8221a0ef, rsp = 0xfffffe0000213970, rbp = 0xfffffe00002139e0 ---
bridge_input() at bridge_input+0x5ff/frame 0xfffffe00002139e0
ether_vlanencap() at ether_vlanencap+0x4a3/frame 0xfffffe0000213a10
netisr_dispatch_src() at netisr_dispatch_src+0x90/frame 0xfffffe0000213a80
ether_ifattach() at ether_ifattach+0x19f/frame 0xfffffe0000213ab0
ath_dfs_get_thresholds() at ath_dfs_get_thresholds+0x81ce/frame 0xfffffe0000213b30
intr_event_execute_handlers() at intr_event_execute_handlers+0x93/frame 0xfffffe0000213b70
db_dump_intr_event() at db_dump_intr_event+0x796/frame 0xfffffe0000213bb0
fork_exit() at fork_exit+0x84/frame 0xfffffe0000213bf0
fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe0000213bf0
--- trap 0, rip = 0, rsp = 0xfffffe0000213cb0, rbp = 0 ---

Sponsored by: Citrix Systems R&D
Approved by: xxx

dev/xen/netback/netback.c:
 - Take the rx_lock when modifying xnb->carrier.
 - Disconnect the interface before removing it.
---
 sys/dev/xen/netback/netback.c |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/sys/dev/xen/netback/netback.c b/sys/dev/xen/netback/netback.c
index 9097140..a8bec76 100644
--- a/sys/dev/xen/netback/netback.c
+++ b/sys/dev/xen/netback/netback.c
@@ -1073,9 +1073,14 @@ xnb_shutdown(struct xnb_softc *xnb)
 
 	xnb->flags |= XNBF_IN_SHUTDOWN;
 
+	mtx_lock(&xnb->rx_lock);
+	xnb->carrier = 0;
+	mtx_unlock(&xnb->rx_lock);
+
+	xnb_disconnect(xnb);
+
 	mtx_unlock(&xnb->sc_lock);
 	/* Free the network interface */
-	xnb->carrier = 0;
 	if (xnb->xnb_ifp != NULL) {
 		ether_ifdetach(xnb->xnb_ifp);
 		if_free(xnb->xnb_ifp);
@@ -1083,8 +1088,6 @@ xnb_shutdown(struct xnb_softc *xnb)
 	}
 	mtx_lock(&xnb->sc_lock);
 
-	xnb_disconnect(xnb);
-
 	mtx_unlock(&xnb->sc_lock);
 	if (xenbus_get_state(xnb->dev) < XenbusStateClosing)
 		xenbus_set_state(xnb->dev, XenbusStateClosing);
-- 
1.7.7.5 (Apple Git-26)

